bi-directional socket to tcp communication - linux

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?

Related

Can a TCP connection between two local processes be closed without either process being involved?

I have two processes written in two different programming languages that exchange information via a local TCP connection. One process is starting the other but their lifetime must be shared, i.e. if one dies, so does the other and vice versa.
I would like to use the TCP connection as the mechanism to detect if the other side is crashing, but I'm not sure if it's safe. I wonder if there are cases where the connection could be closed for other reasons than one of process crashing or exiting.
Edit:
Ideally, the system needs to be portable across OS which is why TCP connections are used instead of Unix domain socket.
I know that it's possible to use administrative tools to kill the connection. What I want to know is if there are cases where in normal circumstances (both processes running fine) the connection would be close.
If the computers that are serving your processes are distant, then of course network problems along the way may cause problems, otherwise it's not trivial to close a connection. A tool such as "tcpkill" can close connections that originates or terminates on the local computer, and if you cross a firewall, then of course the firewall admin may close connections going through.
I think your scheme would work fairly well; if something causes the network connection to go down, then both your processes will terminate, so your worst case scenario would be excessive downtime - which I wouldn't expect from a connection through a normal network.
tcpkill: https://linux.die.net/man/8/tcpkill
You can use iptables to firewall the ports while the connection is running. By either ignoring packages or sending RSTs you could simulate different scenarios: remote host died, remote host closing the connection.
Examples:
# drop packages
iptables -p tcp --dport PORT_NUM -j DROP
# send RST
iptables -p tcp --dport PORT_NUM -j REJECT --reject-with tcp-reset
I've used the destination port above, to filter based on source port use --sport
If one side crashes (or closes/shuts-down its socket through any other means), the other one will see the socket as readable and get EOF on an attempted read.
You can inspect this behavior easily by observing a client-server nc pair, possibly with strace.
Server:
strace nc -l localhost 3333
Client:
strace nc localhost 3333
Whenever one side is killed (e.g., with Ctrl+C, Ctrl+\ or kill), the other side gets EOF (== a read of 0 bytes) ASAP.

Trying to capture unidirectional tcp data on a server

I'm trying to test linux behavior for unidirectional tcp capture using tcpdump.
The scenario is that Server A is sending packets to destination Y through a switch M. At the same time, M will also be sending the same packets to destination Z, where I'd like to capture all packets. The connection A to Y is a tcp connection.
In order to synthesize the above scenario, I have 3 terminals open on server Z running the following commands:
nc -l 0.0.0.8 4444
telnet -b 0.0.0.10 0.0.0.8 4444
tcpdump -i <interface name associated with 0.0.0.8> port 4444
0.0.0.8 and 0.0.0.10 are separate NIC cards in separate slots, slot 1 and slot 6 in this case.
From the telnet session, i'm successful in sending data, however, tcpdump isn't capturing any packets. If I remove the port 4444 from the terminal 3, I'm seeing data from within my network, but never anything from the telnet session. I should also note that I'm not receiving an error message either.
I'm assuming, b/c I read it on the internet, that telnet creates a tcp connection, which is why I believe that tcpdump should work. Am I wrong here? Should I be doing something else? Can't use WireShark or the like on this server.
Also, on terminal 3 I've also tried tcpdump host 0.0.0.8 port 4444 to no avail. Many thanks for any suggestions.
If node M is truly a switch and not a hub, then node Z should never receive the TCP packets destined for node Y.
TCP is a connection based protocol. That is to say that when node A wants to talk to node Y, it will first broadcast an ARP request asking for node Y's MAC address (note that all nodes attached to the switch will see this packet). When node Y responds directly to node A with it's MAC address, then node A will initiate a TCP connection directly to node Y.
If node M is a switch, it will only forward packets destined for MAC address F directly to the port which it knows to be attached to the node having MAC address F. It will never forward that packet to all ports, but only to the destination node's port.
On the other hand, if node M is a hub, it will always forward all packets to all ports regardless of destination.

Firewall-Iptables-Linux : how to force the same source port for all outgoing packets

I'am developing an application with tcl language composed by several processus.
each processus has to send a data using a socket (IP, Port) to an external IP address.
I should use only the port 5060 (as I'm simulating a SIP server).
The problem is that only one thread can use the port 5060 each time when using the socket (parallel threads using the same source port is then impossible) so I should resolve this.
I wonder if I can use linux iptables to change source port used by each thread when several threads are running simultaneously (each one on a different socket) ==>all transmitted packets from the machine are with the same source port 5060.
Any suggestion or information is welcome.
(I need a concrete example if the case)
Thank you very much in advance.
Why can you not use this from multiple threads? Outgoing packets should not have any contention - this would only be an issue when binding to a port for incoming connections, which can only be done by a single thread - if this is the case, your application design is flawed in that only one thread should be accepting connections, and handing them off to workers.
To answer the question asked... This iptables rule should redirect all outgoing packets to a specific port.
iptables -I OUTPUT -j REDIRECT --to-port 5060
If you want to bind this to a specific interface
iptables -I OUTPUT -i eth0 -j REDIRECT --to-port 5060
Or only when talking to a specific destination
iptables -I OUTPUT -s www.xxx.yyy.zzz -j REDIRECT --to-port 5060

how to test user space tcp/ip stack?

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.

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