how to test user space tcp/ip stack? - linux

I am working on a user space tcp stack (mostly just for fun) and I am having some trouble testing it against the unix tcp stack. Currently the only form of testing is done via unit tests. However, I want to test my tcp stack against a real kernel tcp stack. I tried the following setups without much success.
using raw sockets: I wrote a simple echo tcp server that accepts connection using the kernel tcp socket. The tcp server listens to port 8080 on localhost. My tcp client uses the user space tcp stack. However, the kernel sends a tcp rst whenever the client sends a syn to the server. It kind of work after I modified iptable to drop all tcp rst packets. However, even though the 3 way syn, syn+ack, ack handshake is established, the server cannot recv any packet that my client sends. I eventually gave up on raw sockets.
using tun/tap: Similarly the echo server uses kernel tcp socket and listens on localhost port 8080. The client opens a tap device. The tap device has an ip of 10.0.0.1 and my client assumes an ip of 10.0.0.2. I am able to ping 10.0.0.2 from my computer. However, when my client sends a syn to the tcp server over the tap device, the server does not respond.
Note: I am using ubuntu 12.04.

You can use the conntrack tool to try getting more information on why it's not working with using raw sockets. If for some reason the kernel gets confused about the state of the tcp connection, it may be deciding to reset it. You could try telling the kernel not to track connections to rule this out by setting a notrack rule in the raw table. Something like
iptables -t raw -A PREROUTING -p tcp --port 8080 -j NOTRACK
Try using tcpdump on the tun/tap device and iptables counts to see where the packet gets dropped. I would also try tun devices instead so you only have to worry about layer 3.

Related

DOES router or linux kernel change the tcp headers and ip headers of packets

I was looking into raw sockets. so I created one raw socket client and other one is server. on two different computers. I am using ISP provided router. so I sent spoofed packet (with iphdr struct's saddr of different computer on same network) from client but when the packet received at the server the source ip in packet's ip header was correct (the real sender address=client address) plus the source port and destination port of tcphdr were something different too (which really didnt make sense). So I assumed that my ISP provided router is doing something funny -- OR I am completely wrong correct if this is a normal ip protocol. if I am correct then what steps should i take to configure my router so it does not mess up with tcp and ip headers of incoming packets plus the sync=1 at sender's end became sync=0 of tcphdr. I am using local IPs plus I am trying to implement tcp using raw socket server. I have configured iptables on server as well with sync allowed on my bounded port
iptables -I INPUT -p tcp --dport xxxx --syn -j ACCEPT
WHat settings do I need to do on server in iptables so my socket incoming packets wont be dropped nor any header be touched so I can get all packets required for tcp to keep coming in. plus what setting do I need to do on router so,if its cause problem then, it wont
Update 1:
after spending some time to the problem I found that one cause could be my kernel tcp stack dropping the incoming sync packets. so I looked around and found that in the tcp stack there is work done to make this happening. So I changed the sysctl.conf in /etc to allow sync packets to come in through by adding or uncommenting this line
net.ipv4.tcp_syncookies=1
Then I rebooted the system but still no difference. is it because somehow I have to reload my sysctl.conf file. if this is the case or any related case then please fill in.
Update 2
I have reloaded sysctl.conf after allowing syn packets and now I am getting syn packets from client application. but the destination port different. also along with syn=1, ack=1 is also coming in same packet. is this also something kernel is doing. please explain. as long as I know this is not how tcp works (tcp handshake) and I am connecting from client using stream socket

bi-directional socket to tcp communication

I have a software X listening and writing to TCP port. I.e. It creates a Server Socket and a client that reads and writes to TCP.
And I have a serial device ttyUSB0 which can accept data in a format that provides software X and send data back to serial.
I want to feed data from serial to TCP and vice versa, so that it looked transparent to software X and to a serial ttyUSB0.
I was trying to use socat. Like,
socat -d -d -d -d -x TCP-LISTEN:7758,fork,reuseaddr FILE:/dev/ttyUSB0,b9600,raw
But it seems that it does not work. Looks as if listener on TCP port blocks binding. I have
E bind(3, {AF=2 0.0.0.0:7758}, 16): Address already in use
Could someone please help me with my problem?
As some commenters already mentioned, you can't make a TCP connection with two listeners. For a TCP connection you always need a server (listener) and a client.
As your software is already a server (listening on port 7758) socat should be run in client mode (connecting to your server).
This can be done with the option TCP:<host>:<port>, for example like this (adapted your example, not tested!):
socat -d -d -d -d -x TCP:localhost:7758 FILE:/dev/ttyUSB0,b9600,raw
This is not possible for TCP. Note that you could specify SO_REUSSEADDR but this will not cause BOTH listening applications to receive the data: only one app (decided at "random" by the OS) will receive the data, while the other will "hear" nothing.
If you can use multicast UDP you can do this.
See Can two applications listen to the same port?

When using a raw socket for TCP traffic, keep kernel from receiving incoming packets

I am running some security tests which require the use of a non-standard TCP socket, to generate a behaviour that a normal TCP stack would not follow. I use a raw socket to generate such traffic.
When the reply from the other end point is received, the TCP connection is unknown to the kernel and issues a RESET. To prevent this from happening, the normal solution is to define an iptables rule that drops all outgoing RESET (e.g. iptables -A OUTPUT -p tcp -dport 50000 --tcp-flags RST RST -j DROP).
However, in my particular case, RESET is also a valid segment to generate during the testing. What I need is a way to filter out all segments from that connection so the kernel TCP stack is not involved and yet have access to all the segments in my raw socket.
Any ideas how can I achieve this? Is this possible with iptables?
Thanks in advance
Luis
Trying to use the host's IP address and fighting Linux's TCP/IP stack is calling for trouble.
Instead, I would use a separate IP address, route that to a tun device and get the raw IP packets from the tun device instead of using a raw socket (some sample code to interface a tun device is available from http://www.secdev.org/projects/tuntap_udp/). That way the Linux TCP/IP stack won't get in your way (except for routing puposes).

TCP : Simulate EINPROGRESS from server side (linux)

How can i simulate a connect from a non-blocking client to experience a EINPROGRESS error ?
What can i do from the server to return such error to the client (i.e tuning some tcp timers, raw socket server etc..)
When connecting to localhost TCP always connects immediately, hence connect() doesn't return EINPROGRESS.
You can simulate that in client by "pretending" that connect() returned EINPROGRESS and waiting till the client socket becomes ready for write (as if connected after EINPROGRESS). In fact, some libraries do just that for non-blocking connect() to avoid two different code paths for immediate and for slow connect.
I had to do something similar recently and I came across this thread. I used iptable rules to solve my problem. EINPROGRESS is not something that is returned by the server. If a connect can't complete immediately, the return code from connect is -1 and the errorno is set to EINPROGRESS. Once connect sends out the SYN packet, your connect will complete (given that you are connecting to a valid IP address, and everything else is okay with the network).
If you can change iptables on the client side, then the easiest way to simulate EINPROGRESS is to create an iptable rule to drop outgoing SYN packets to the server's IP address and port.
iptables -A OUTPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -d serverip --dport serverport -j DROP
Keep in mind that this only works if you don't want the connect to ever complete.

Linux: how to send TCP packet from specific port?

How to open a raw socket for sending from specific TCP port? I want to have all my connections always go from a range of ports below ephemerals.
If you are using raw sockets, then just fill in the correct TCP source port in the packet header.
If, instead, you are using the TCP socket interface (socket(), connect() and friends), then you can set the source port by calling the bind() system call for the client socket - exactly as you would to set the listening port for the server socket.
Making a tcp connection using raw sockets is somewhere between difficult and impossible; you'd need to implement the entire tcp protocol in your program AND also stop the kernel from sending its own replies to the packets (if the kernel has IP bound on that address on that interface).
This is probably not what you want. However, if you did want it, it is trivial to send tcp frames with any source port you want, as you get to specify it in the tcp header, which of course, if you're implementing your own TCP layer, you'll need to understand.

Resources