odd tcp behavior

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi There,
playing with my linux tcp/ip stack i noted an odd behavior. It seems that the linux kernel,if it has an RST packet to send to any ethernet host via
loopback (yes, a strange and unusefoul packet that will never reach its
destination) will replace destination ip address with one of its own (ie the ip
address of eth0).


I've a linux machine configured as eth0=10.0.0.45 with sshd server running, and another machine configured as eth0=10.0.0.68 with all tcp ports closed (note that no packets will reach this computer during the following tests).

i tried to send a source-spoofed packet from 10.0.0.45 to 10.0.0.45's sshd port
using 10.0.0.68 as source address:

As expected hping gets no responses, in fact kernel routed this packet to loopback (because 10.0.0.45 is the address of the local machine) and discarted
it because 10.0.0.68 is not the local machine.
Setting 10.0.0.45 (or 127.0.0.1) as source address it will result in
the correct SYN/ACK/RST sequence.


// 1st test: using 10.0.0.68 as source address
~# hping -S -c 1 -p 22 -a 10.0.0.68 10.0.0.45
[...], 100% packet loss

~# tcpdump -n -i lo
IP 10.0.0.68.2375 > 10.0.0.45.22: S 2140892290:2140892290(0) win 512


// 2nd test: using 127.0.0.1 as source address
~# hping -S -c 1 -p 22 -a 127.0.0.1 10.0.0.45
len=44 ip=10.0.0.45 ttl=64 DF id=0 sport=22 flags=SA seq=0 win=5840 rtt=0.7 ms
[...], 0% packet loss

~# tcpdump -n -i lo
IP 127.0.0.1.2628 > 10.0.0.45.22: S 530014843:530014843(0) win 512
IP 10.0.0.45.22 > 127.0.0.1.2628: S 1919550047:1919550047(0) ack 530014844 win 5840 <mss 1460>
IP 127.0.0.1.2628 > 10.0.0.45.22: R 530014844:530014844(0) win 0


Ok, this is exacly what i was expecting...
The RST packet is generated by the kernel because the initial SYN packet
is generated by an user-space program and not by the kernel itself.

The strange thing appens when i try to send a SYN packet to a closed port

// the 1st test on a closed port
~# hping -S -c 1 -p 221 -a 10.0.0.68 10.0.0.45
[...], 100% packet loss


~# tcpdump -n -i lo
IP 10.0.0.68.2626 > 10.0.0.45.221: S 2096293894:2096293894(0) win 512
IP 10.0.0.45.221 > 10.0.0.45.2626: R 0:0(0) ack 2096293895 win 0
                   ^^^^^^^^^


In this case the kernel generated a reply packet but the destination address
is 10.0.0.45 istead of 10.0.0.68..and i can't understand why..


and.. what if i forge the same packet but with 127.0.0.1 as source...
as the second test suggests, the kernel should generate a valid RST packet
with 10.0.0.45 as source and 127.0.0.1 as destination...

// the 2nd test on a closed port
~# hping -S -c 1 -p 221 -a 127.0.0.1 10.0.0.45
[...], 100% packet loss

~# tcpdump -n -i lo
IP 127.0.0.1.1445 > 10.0.0.45.221: S 1233377333:1233377333(0) win 512
IP 10.0.0.45.221 > 10.0.0.45.1445: R 0:0(0) ack 1233377334 win 0
                   ^^^^^^^^^

..the same strange behavior as before, the RST packet is destinated to 10.0.0.45


Now i'm quite confused...




I've also tried to route all traffic for 10.0.0.68 to loopback, and i repeated
the above tests again


~# route add -host 10.0.0.68 dev lo

~# hping -S -c 1 -p 22 -a 10.0.0.68 10.0.0.45
len=44 ip=10.0.0.45 ttl=64 DF id=0 sport=22 flags=SA seq=0 win=5840 rtt=0.6 ms
[...], 0% packet loss

~# tcpdump -n -i lo
IP 10.0.0.68.2696 > 10.0.0.45.22: S 1116486620:1116486620(0) win 512
IP 10.0.0.45.22 > 10.0.0.68.2696: S 2841752913:2841752913(0) ack 1116486621 win 5840 <mss 1460> IP 10.0.0.45.22 > 10.0.0.68.2696: S 2841752913:2841752913(0) ack 1116486621 win 5840 <mss 1460> IP 10.0.0.45.22 > 10.0.0.68.2696: S 2841752913:2841752913(0) ack 1116486621 win 5840 <mss 1460>


Ok, now the kernel knows that 10.0.0.68 must be routed to loopback and generates a SYN/ACK response. This syn/ack packet is repeated n times because 10.0.0.68 will never receive it so it will never send a valid RST response. And this is
exactly what i was expecting.

Let's try to send the same packet to a closed port..


~# hping -S -c 1 -p 221 -a 10.0.0.68 10.0.0.45
[...], 100% packet loss

~# tcpdump -n -i lo
IP 10.0.0.68.1962 > 10.0.0.45.221: S 763165225:763165225(0) win 512
IP 10.0.0.45.221 > 10.0.0.45.1962: R 0:0(0) ack 763165226 win 0
                   ^^^^^^^^^

here it happens again..




note that routing to loopback the whole 10.0.0.0 network instead of 10.0.0.68
only makes no difference.

I've tested it against 2.4 and 2.6 linux kernels and both kernels seems to be affected. I've also tested it against some bsd systems (FreeBSD, OpenBSD, MacOSX)
and they seems to be ok..

any ideas??

ciao,
poplix

-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux