Using socat to send arbitrary IPv4 traffic
One of the more interesting tasks I've had recently was to figure out what a firewall did when IPv4 was sent through it. Sounds simple enough right? Just place something like a web server on one side of the firewall and then use curl
to access it. This does in fact send IPv4 traffic. That covers TCP. Some clever use of the netcat
command can then be used to quickly test UDP connectivity as well. If you're knowledgeable of network protocols, you might also know that ICMP exists and that ping
can send ICMP packets.
But what about the rest of IPv4? Wikipedia does in fact list dozens of other known protocols. Some of these are reasonably well known, like IP in IP. Others such as "UDP Lite" are completely unknown to me. The main issue with trying to test a firewall with such traffic is that even if software is well known for a particular protocol is unlikely to be as accessible as a tool like curl
. After all, I don't really need to set up a proper IP encapsulation link. I just need to find out how the firewall handles packets that appear to be IP in IP encapsulation.
Using socat
As it would turn out, there is in fact a solution to this. The socat
tool is designed to be a command line tool for interacting with sockets. You can send an arbitrary packet by combining some commands line tools together
echo -ne 'bob' | sudo socat - ip4-sendto:127.0.0.1:4
This particular example sends an IPv4 packet to a destination IP of 127.0.0.1 with protocol number 4. The packet contents is the string 'bob' which as you might guess does not conform to any actual protocol standards. You can actually see this with tcpdump
running on your local computer
$ sudo tcpdump -i lo -n -vvvv -s 65535 -X 'ip and not icmp and not tcp and not udp' tcpdump: listening on lo, link-type EN10MB (Ethernet), snapshot length 65535 bytes 21:33:35.683579 IP (tos 0x0, ttl 64, id 10901, offset 0, flags [DF], proto IPIP (4), length 23) 127.0.0.1 > 127.0.0.1: IP6, wrong link-layer encapsulation (invalid) 0x0000: 4500 0017 2a95 4000 4004 124c 7f00 0001 E...*.@.@..L.... 0x0010: 7f00 0001 626f 62 ....bob ^C 1 packet captured 2 packets received by filter 0 packets dropped by kernel
Since in my case I just needed to confirm the firewall behaviors in the presence of different IPv4 protocols, this worked out great. I can send basically any packet that appears to be any of the protocols. If I actually need to send a valid packet I could craft one as well
IPv6
Of course socat
supports more than just IPv4. So you can use this technique to send IPv6 traffic as well.
echo -ne "Hello IPv6" | sudo socat - 'ip6-sendto:[fe80::5054:ff:feb0:d38e%enp7s0]:136'
Since the address is IPv6, it needs to be enclosed in the square brackets []
. I'm also using a link local address, which means I use the percent sign %
to specify what interface to communicate on. The packet sent looks like this according to tcpdump
03:45:08.016368 IP6 (flowlabel 0xc71b6, hlim 64, next-header unknown (136) payload length: 10) fe80::83eb:45ba:3eda:6a0a > fe80::5054:ff:feb0:d38e: ip-proto-136 10 0x0000: 600c 71b6 000a 8840 fe80 0000 0000 0000 `.q....@........ 0x0010: 83eb 45ba 3eda 6a0a fe80 0000 0000 0000 ..E.>.j......... 0x0020: 5054 00ff feb0 d38e 4865 6c6c 6f20 4950 PT......Hello.IP 0x0030: 7636 v6