netfilter event on packet locally processed ( netfilter C kernel module code) - linux

If an incoming packet comes in AND is locally processed, is there a way to get
notified of that event?
I'm currently using the NF_IP_LOCAL_IN hook. But it looks like this gives all packets destined for the interface. For example suppose tcp packet X comes to port 5000, and there is a socket listening on port 5000. I would like to receive that event.
To clarify, I mean I only want to receive packet X events. All other packets that are not processed locally, (i.e. those that generate ICMP destination unreachable I don't want to be notified about)

Netfilter lives at L3/L4, so it only has access to information up to L4. OTOH, LSMs (Linux Security Modules) have hooks almost everywhere, including socket_recvmsg, which I think should be called only for the packets that you are interested in.
Now, whether you can use this depends on your situation. Is there a LSM already running on your environment? If the answer is yes, can you make and insert a policy for your LSM that would be enough for your purposes?

Well, the interface must be lo.
Or I don't understand why LOCAL_IN hook doesn't satisfy you.

Related

Linux Raw Sockets: Block Packets?

I've written my own packet sniffer in Linux.
I open a socket with socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) and then process the Ethernet packets - unpacking ARP packets, IP packets (and ICMP / TCP / UDP packets inside those).
This is all working fine so far.
Now I can read packets like this - and I can also inject packets by wrapping up a suitable Ethernet packet and sending it.
But what I'd like is a means to block packets - to consume them, as it were, so that they don't get further delivered into the system.
That is, if a TCP packet is being sent to port 80, then I can see the packet with my packet sniffer and it'll get delivered to the web server in the usual fashion.
But, basically, I'd like it that if I spot something wrong with the packet - not coming from the right MAC address, malformed in some way, or just breaking security policy - that I can just "consume" the packet, and it won't get further delivered onto the web server.
Because I can read packets and write packets - if I can also just block packets as well, then I'll have all I need.
Basically, I don't just want to monitor network traffic, but sometimes have control over it. E.g. "re-route" a packet by consuming the original incoming packet and then writing out a new slightly-altered packet to a different address. Or just plain block packets that shouldn't be being delivered at all.
My application is to be a general "network traffic management" program. Monitors and logs traffic. But also controls it too - blocking packets as a firewall, re-routing packets as a load balancer.
In other words, I've got a packet sniffer - but if it sniffs something that smells bad, then I'd like it to be able to stop that packet. Discard it early, so it's not further delivered anywhere.
(Being able to alter packets on the way through might be handy too - but if I can block, then there's always the possibility to just block the original packet completely, but then write out a new altered packet in its place.)
What you are looking for is libnetfilter_queue. The documentation is still incredibly bad, but the code in this example should get you started.
I used this library to develop a project that queued network packets and replayed them at a later time.
A bit of a tangent, but it was relevant when I was resolving my problem. Blocking raw packets is relatively complicated, so it might make sense to consider doing that at a different layer. In other words, does your cloud provider let you set up firewall rules to drop specific kind of traffic?
In my case it was easier to do, which is why I'm suggesting such a lateral solution.

Respond to a Packet Received in The NetFilter at Kernel

I'm working on Linux 4.13.x. And I'm considering to send a packet response in the kernel.
Consider an echo TCP or UDP server running in the userland and there is also another node running a TCP or UDP client. Clients are sending requests to the server. I want to send the packet response back to the client without any involvement of server application running at userspace.
Here is my thoughts about this problem:
I started thinking how it is possible and I come across to a solution like netfilter. If I can capture the packets in NF_INET_PRE_ROUTING and then try to swap the source and destination IP addresses of IP header and also swapping the ports in the TCP header, then according to this answers and this presumably modified packet should be forwarded to the originator throughout the routing system.
Actually, I tried this scenario and it seems it is not possible to do so from netfilter hooks, however, I'm not sure of it. I thought that it is not working since it has problem with checksums because I'm manipulating packets so I did another experiment to figure this issue out. I just change the packet data and everything worked well. I think checksums don't have any problem since they will be check at NIC while receiving and also same situation while sending so manipulation in between doesn't make anything wrong. I also activate the IPv4 forwarding at the server host(sysctl.config) still nothing changes.
I don't want to create new packet, I only want to alter this packet and send it back. There is another similar question which is creating another packet. Moreover, I'm just thinking why this scenario is not working? But based on the netfilter's architecture it should work.
Thank you
I am also working on this, actually kernel validate the source ip address after ip_rcv function in NF_HOOK which check the source ip address. So just try below command:-
sudo sysctl -w "net.ipv4.conf.all.rp_filter=0"
after doing this also disable your interface from which you send and receive packet just like below:-
sudo sysctl -w "net.ipv4.conf.enp2s0.rp_filter=0"

How do I test a custom TCP implementation on Linux?

For learning purposes I'm implementing TCP (for now just RFC 793) but I have no
idea how to test it. Most TUN/TAP stuff on the internet are out of date (e.g.
Linux API calls no longer work) and just doesn't explain enough. In addition, I
feel like a creating a device and forwarding packages etc. are not the best way
for learning purposes. For example, I'd rather only override socket(),
listen(), connect(), accept(), send(), recv() etc. in a program rather
than forwarding all ethernet traffic to a device/program that does the
bookeeping for the whole system rather than for a single program.
I'm wondering if this is possible. If not, I'd like to know the simplest way to
test a TCP implementation on Linux.
Because I'm following RFC 793, it'd be great if I could have an IP (Internet
Protocol as mentioned in the RFC) API in my application. Is this possible or do
I have to mess with TUN/TAP stuff?
Thanks..
If we talk about research I strongly recommend you read Engineering with Logic: Rigorous Test-Oracle Specification and
Validation for TCP/IP and the Sockets API
It contains section about testing TCP/IP implementation:
"EXPERIMENTAL VALIDATION: TESTING INFRASTRUCTURE"
You could try setting up two peers, one using a RAW socket and the other a TCP socket.
If they can communicate and packets are really delivered/recovered the same way TCP does, you know that your custom implementation is successful.
C sockets
C RAW sockets
C TCP implementation
All you need is to intercept all tcp packets with bits (syn, ack, fin, etc.) your application has sent and to see if it works properly:
It could simply be done with wireshark or other sniffer. When testing you will see all tcp packets with bits you've sent.
In order you want to see linux system calls which your application are calling, you can use GDB or any other debugger.

Internet socket behavior when communicating within the same host

I am recently writing some tool for testing some network processes that run across different hosts.
I am tempted to the idea that when testing, instead of running the client and server in different hosts, I can run them within one host.
Since the client and server are using TCP to communicate, so I think this should be fine, except one point below:
Is the TCP socket behavior the same when communicating data within the same host as the case of across hosts?
Will the data be physically present to the NIC interface and then routed to the target socket? Or the kernel will bypass the NIC interface under such scenarios? (Let's limit the OS as only Linux here for discussion)
There seems little specification regarding to such case.
==== EDIT ====
I actually notice some difference between intra-host and inter-host communications.
When doing inter-host communications, my program can successfully get hardware timestamp. But with the exact same code to run within the same host, the hardware timestamp disappears. When supported and enabled, hardware timestamp of TCP packet is available, and is returned as the ancillary data of recvmsg along with the received TCP data. Linux kernel timestamp doc has all the related info.
I checked the source code, the only difference is that whether the sender is within the same host of the receiver, no other difference.
So I am wondering whether Linux kernel will bypass the NIC and present the data directly to the receiver when doing intra-host communication, thus cause the issue.
Will the data be physically present to the NIC interface and then routed to the target socket?
No. There is typically no device that provides this capability, nor is there any need for one.
Or the kernel will bypass the NIC interface under such scenarios?
The kernel will not use the NIC unless it needs to send or receive a packet on a network. Typically, NICs can only return local packets if put in a test or loopback mode, which would require them to stop listening to the network.

How to control source ip or port for UDP packet with nodejs

I'm working on an application that interfaces with embedded equipment via the SNMP protocol. To facilitate testing, I've written a simulator for the embedded equipment with Nodejs and the snmpjs library. The simulator responds to SNMP gets/sets and sends traps to the managing application. The trap messages are constructed by the snmpjs library, but sent manually using Node's standard UDP sockets.
This works well when simulating one equipment, but I've run into an issue when attempting to simulate multiple equipment. Specifically, the managing application identifies the source equipment of SNMP traps by analyzing the source IP/port of the UDP packet carrying the trap. This precludes my simulating multiple equipment simultaneously, which is the most common use case for the application.
So, my question is: Is there some way to control/spoof the source IP or port of the udp packet with Nodejs? Or, perhaps, would it be possible to use some kind of proxy to achieve the desired result?
(Note: Running the simulators on a single machine is a strict requirement. Also, it is not sufficient that I have unique IPs/ports for each simulator, I must be able to know their values ahead of time so that I can configure the managing application to interface with them correctly.)
The solution was simple. I overlooked this line from the node documentation for the send method of udp sockets, "If the socket has not been previously bound with a call to bind, it's assigned a random port number..." I just needed to bind the socket to a port first. I've verified this with a test script.

Resources