Create VPN over TCP connection - linux

I need to create a virtual IP network over TCP connection. The hosting system is Linux, with the TUN/TAP kernel driver, it's quite easy to receive & re-inject IP packets of the virtual network.
The difficult part is to transmit the received IP packets to another host. For some non-technical reasons, I can only transmit the packets over TCP protocol but not UDP. Transmit IP packets over UDP is easy, but with TCP it becomes tricky, here's the reason:
UDP protocol doesn't support retransmission/reordering, just like IP. So, if one UDP packet is sent for every received virtual IP packet, the kernel TCP/IP protocol stack would still see virtual IP packet loss/duplication/reordering(those are required for TCP/IP to work well, if those "features" are missing, the TCP connection speed on the virtual network would suffer). If IP packets are transmitted over TCP all required "features" will be missing, unless they are simulated some how.
It seems I have to fake some kind of packet duplication/loss/reordering on TCP connection, or patch the kernel TCP/IP protocol stack. Both options aren't easy.
Is there any other simpler solution to my problem ? or did I just go into a completely wrong direction ? I'm all ears.
==== UPDATE ====
I'm thinking about using raw IP socket (which could get rid of all the TCP retransmission/reordering stuff on the physical network easily while still using TCP packets) to transmit the received virtual network IP packets. But on the receiving host, how can I only receive the packets I'm interested in and return all other IP packets to the kernel TCP/IP stack ?

First of all, you do not want to make a VPN over TCP because you would end up with tcp-over-tcp eventually. The main issue is that the timers of your inner TCP and outer TCP might differ significantly which negatively impacts your TCP session reliability. You can find a bit longer explanation here.
UDP protocol doesn't support retransmission/reordering, just like IP. So, if one UDP packet is sent for every received virtual IP packet, the kernel TCP/IP protocol stack would still see virtual IP packet loss/duplication/reordering(those are required for TCP/IP to work well, if those "features" are missing, the TCP connection speed on the virtual network would suffer). If IP packets are transmitted over TCP all required "features" will be missing, unless they are simulated some how.
This does not make sense, if your outer layer uses TCP as a transport mechanism, nothing stops your inner layer to still use the full ip/tcp stack, including those features. They can conflict badly like I said, but it's not that this functionality disappears or breaks completely.
It seems like you actually want to use TCP just to have the headers and ignore the actual protocol, this would indeed avoid the issues with tcp over tcp. However, once again this is a very bad idea. Flow processing for firewalls, NAT, DPI, tcp boosters, becomes more and more common, if you fake TCP packets you might up stressing those boxes, possibly detoriating your own connection once again.
So you should ask yourself why you can't use UDP, and if no alternative protocol (header) is okay, like GRE or L2TP.

Related

UDP packet re-ordering in linux

I understand that UDP does not guarantee order of packets, but that is at Transport layer.
Does the Linux kernel guarantee ordered UDP packets to user space programs ?
I read that services like DNS and DHCP use UDP and they have daemons running in user
space for that.
If Linux does not provide ordered UDP packets to user space then how do services like
DNS and DHCP work reliably ?
Thanks

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

Convert UDP header to TCP header

I have a typical requirement, I want to have a converter module, that can convert UDP packet to TCP packet.
And I need to do it before the packet can be processed in IP layer.
I will explain this complete scenario using an example
Lets say we have 3 machines A, B and C.
A sent an UDP packet
B received UDP packet
At B, when packet is being given to IP layer (from Link / MAC / Ethernet layer) , I want to get hold of packet. I want to delete the UDP and IP header in packet. I want to add TCP and IP header (assuming C is the destination host).
Now from B machine, packet is sent to C machine
Can somebody help me how this can be done.
I am using linux machines.
Though libpcap can be one of the option (from wireshark), but it is not suitable for me because of performance reasons.
I want a very light weight solution for this problem.
Can't be done. TCP is a stateful, reliable, connection-oriented byte-stream protocol. UDP is a stateless, unreliable, unconnected packet protocol.
The best you can do is, on machine B, open a new socket/TCP connection to C, accept socket/UDP packets from A, and write the contents of those packets to the TCP stream. Data flowing the other direction is a bit more difficult because you have to create UDP packets to A no larger than the maximum UDP packet size supported by your systems.
You can not do it directly but if you will use a UDP VPN than you can do it very easily.
Just connect you system/PC with UDP VPN network and it work as you are want.
check below my image for more information, i am also using same.

Where are the missing TCP packets?

I observed a surprising thing that when there are both udp-based and tcp-based applications sending packets, if the upd-based application sent the packets so fast that the bandwith are nearly filled with udp packets, then the tcp packets would be very hard to send out.
The surprising thing is that though tcp-based application is able to send a few packets out (observed by the return value of write()), the receiver of the tcp packets never receives them. Why? Is that because the tcp-packets arenot finally sent out by the network card? or the tcp packets are actually dropped by routers?
Thanks,
Steve
First, the return value of write() is not an indicator of whether packets were sent. It just indicates that the data was buffered.
Second, if you are saturating the network with UDP packets there will be a lot of packet loss, and TCP being adaptive will adapt to that by sending packets out more slowly. If the packet loss gets too high TCP can basically stop altogether. The solution is not to saturate the network with UDP packets.
This is a simplified answer. There are many articles you can read up on.
UDP is a layer built upon IP. Ditto for TCP. The network card just sends out IP packets. You can look up the various structures for these packets.
TCP is a protocol that uses IP packets but uses a mechanism to try to ensure delivery and rearranges packets in the correct order. See the article on Wikipedia.
Routers are free to drop packets. This can occur when the network is overloaded, network connections are down or the IP packet is corrupted.
So to answer your question their is no preference between UDP or IP to be transmitted from one end to the other.

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).

Resources