What happens to TCP socket when IP address changes? - linux

Is there any error on a socket when writing to it after IP address change?
In my I'm using TCP socket, both read/write (non-passive), no TCP or application keep-alive.
To inspect this case I use socat to connect to a simple echo server on my local network. The connection is OK until I change the client IP address on my router and restart the network interface.
At this point, I can write to a socket without any errors despite the IP of the client was changed, but no messages are being delivered anymore. I wait for some minutes and change the IP back. All the 'stashed' messages which were unable to be sent are being sent.
As far as I understand, when client IP was changed TCP connection does not exist anymore.
Why there are no errors when writing to the socket when IP was changed? Is this specific to a Linux TCP stack or specified by TCP/IP?

A TCP connection is defined by source IP, source port, destination IP, and destination port. Changing the client's IP address on your router does not cause the connection on your client and server to cease to exist immediately; however, if you leave the router in this state long enough, the connection will eventually cease to exist after certain amount of retries and timeouts have occurred. The exact amount is determined via configurable kernel parameters both on your client and on your echo server. You can inspect these parameters with sysctl -a | grep tcp
After you've changed the client's IP address on your router, the client is still able to send packets to the server, and the server is also able to receive these packets, but the server's attempt to reply/acknowledge back to the client is unable to be routed back to the client. This leads to retries up to a certain limit on the client (which is why you saw no errors on the client side). Once you've reverted the client's IP back on your router, the server is able to communicate with the client again as the router is now able to correctly route the server's packet to the client.
This retry behavior is not specific to the Linux TCP stack. rfc 2988 defines the standard algorithm that senders are required to use to compute and manage their retransmission timer.

Related

Do all the sockets in a namespace connect to the same port on the server in socket.io?

I thought when a server is started, it creates a specific number of TCP ports on a computer. so whenever a new connection comes in, it assigns a port to that client ('connection'). Recently I opened tutorialsPoint website 'https://www.tutorialspoint.com/socket.io/socket.io_namespaces.htm' and in there is written:
"Socket.IO allows you to “namespace” your sockets, which essentially means assigning different endpoints or paths. This is a useful feature to minimize the number of resources (TCP connections) and at the same time separate concerns within your application by introducing separation between communication channels. Multiple namespaces actually share the same WebSockets connection thus saving us socket ports on the server".
This part i did not understand: "Multiple namespaces actually share the same WebSockets connection thus saving us socket ports on the server". My question is how can all the connections share a single port on the web-server.
Any help will be highly appreciated.
Do all the sockets in a namespace connect to the same port on the server in socket.io?
Yes, they do.
First off socket.io is built on the underlying webSocket protocol. A webSocket connection starts with an http connection which is built on top of a TCP connection and then the two sides agree to "upgrade" the protocol to start talking the webSocket protocol instead of the http protocol.
So, when a socket.io connection comes in, it's initially an http connection.
Second, any TCP server is listening for inbound connections on a known port. The client must know what that port is and the client attempts to connect to the combination of IP address and port. A regular TCP server using only one network adapter will just be listening on that one port. All inbound client connections will arrive on that one port.
I thought when a server is started, it creates a specific number of TCP ports on a computer. so whenever a new connection comes in, it assigns a port to that client ('connection').
That's not how it works. A listening server creates a passive socket listening for inbound connections on one specific port. When a TCP client initiates an outbound connection, that client picks a dynamically selected port number for that outbound connection (that is unique for that client and not currently in use). This source port number is typically not visible in TCP, http, webSocket or socket.io programming (though you can see what is is if you want - you just don't have to use it yourself at the level we usually program at). It's part of the TCP plumbing that helps packets get delivered to the right socket. So, at that point it has a source IP address and a source port number. It then attempts to connect to a target IP address on a target port.
That unique combination of those four parameters:
source IP
source port (dynamically assigned on the client)
target IP (known in advance by the client)
target port (known in advance by the client)
defines a unique TCP connection. No two TCP connections will have the same four parameters. If the same client makes another TCP connection to the same target IP and port, it will be assigned a different source port number and thus it will be a different unique combination.
There's one little (somewhat confusing) aspect here that I'll make you aware of, but not try to overly explain or confuse things by. Many clients are actually on a private network and have a private IP address. That private IP address is not what the server actually sees as the source of the connection. At some point the connection goes through a gateway that connects the private network to a public network. This gateway will do NAT (network address translation). It will swap the private source IP/port for a public source IP/port that corresponds to the gateway itself. It remembers what it swapped so that when packets come back the other directly, it can swap it back. So, the target server actually believes it's communicating with the gateway, but anything the target sends to the gateway is "forwarded" onto the private IP address/port of the original sender. So, you don't really need to understand the details of the gateway except that it's serves as a broker between the private IP address of some computer on a private network and some computer on the public internet that you are trying to connect to. It does what's called "network address translation" to make this all work. For the rest of the discussion, you should forget about this and just pretend that both source and target are both on the public internet with public IP addresses (even though that is almost never the actual case, but the gateway makes it just work as if they were).
"Socket.IO allows you to “namespace” your sockets, which essentially means assigning different endpoints or paths. This is a useful feature to minimize the number of resources (TCP connections) and at the same time separate concerns within your application by introducing separation between communication channels. Multiple namespaces actually share the same WebSockets connection thus saving us socket ports on the server".
In socket.io, when you connect on a namespace, you are creating a new underlying webSocket connection to the same target IP/port. A server can have many inbound connections to the same IP/port. Each is given it's own TCP socket and the four parameters mentioned above uniquely define each one. When an inbound network packet arrives at the lowest level, TCP can tell which source IP and source port it came from and which target IP/port is was sent and that allows the TCP driver to figure out which socket that packet belongs to so that the packet can be delivered to the code that is monitoring that specific socket.
This part i did not understand: "Multiple namespaces actually share the same WebSockets connection thus saving us socket ports on the server". My question is how can all the connections share a single port on the web-server.
To use a namespace in socket.io, you make a new socket.io connection to that specific namespace. You don't use multiple namespaces on a single socket.io connection. But, a namespace operates at a higher level than the TCP or webSocket connection logic. It rides on top of that in the application layer. So, all namespace connections, no matter which namespace you are using, connect to the same server on the same IP and same port. Once the connection has been established, socket.io sends some data that it would like a "logical" connection on this namespace and then the receiving socket.io code is informed that the new connection belongs in this namespace.
Here's a useful article to read on the topic: Understanding socket and port in TCP.

Azure VM outbound TCP connection breaks after several munutes

I have a virtual machine running Windows Server 2012R2 within Azure cloud. This machine has its private and public IP address statically assigned. On that machine, I'm running client application (Jenkins Agent to be specific). This client opens TCP connection to its server (Jenkins Master), which is running outside of Azure cloud (behind some public IP address). TCP connection is established fine.
In order to keep this connection alive, both the client and the server are "pinging" each other every 4-5 mins. This "pinging" is done by exchanging several TCP packages through that opened TCP connection.
After some random time interval, client can't reach the server anymore and the server can't reach the client anymore. Therefore, connection timeout exceptions are thrown on both client and server ends.
To analyze the issue, I was tracking this communication with Wireshark, which is running on Windows Server in Azure cloud (where the client application is running). While the communication works well, Wireshark shows TCP traffic is exchanged between:
- client's private IP address / local port
- server's public IP address / port
This seems perfectly logical because Azure machine (client) is not aware of its public IP address and publicly visible port (after NAT is applied).
When the issue starts occurring, I see that both client and server are sending TCP retransmission packets, which means that neither of them received TCP:ACK packet to some previously sent TCP:PSH packet. Most strange of all is that client machine was receiving these TCP retransmissions from the server but the problem is: those packages are not sent to client's private IP/local post. Those packages are shown in Wireshark as being sent to client's public IP and publicly visible port! Obviously the client application doesn't receive these packages because machine's NIC/driver discards them (which is also expected).
QUESTION: Does anyone have any idea why the TCP responses sent to Azure machine's (client's) public IP address and publicly visible port sometimes reaches the machine itself without NAT translation being applied to that content?!
After 3 days of tracking the status, no issue re-occurrences have been noticed! So I'm resolving this question with conclusion: more frequent client/server pinging (i.e. keeping connection alive) definitely works around this Azure problem.

Client security using UDP

Introduction
I am currently trying to build up a networking layer for Unity from scratch. Currently I am testing the communication via UDP using Node.js for the server and the client. However I guess the language of the implementation will not matter for what I am asking for.
Current approach
The current approach using Node.js for the server and the client is pretty basic. I simply send a packet from a client to my server while the client and the server are not in the same local network. Both are behind a router and therefore also behind a NAT.
The server then sends back an answer to the IP and port received within the UDP packet that was sent from the client.
Problem
I am curious about the security on the client side regarding to ports being opened on the client machines and routers. So far I assumed that I don't need to do anything to secure the client from attackers or anything else that can do something with the ports that are used by my application. The following assumption shows why I think that I don't need to do anything to secure the clients.
Assumption
Server is setting up callbacks.
Server starts listening to a specific port which is also forwarded to the servers machine within the router.
Server now will call a callback when a UDP message was received. The server then will send a UDP message to the address and the port of the client obtained by the message received.
Client is setting up callbacks.
Client starts listening to port 0 which for Node.js's dgram means:
For UDP sockets, causes the dgram.Socket to listen for datagram messages on a named port and optional address. If port is not specified or is 0, the operating system will attempt to bind to a random port. - https://nodejs.org/api/dgram.html#dgram_socket_bind_port_address_callback
So the operating system now knows that packets sent to this port belong to my application.
Nobody can use this for something malicious.
Client, which knows the servers address and port, starts the process of sending a UDP message to the server.
Clients router receives the UDP message. NAT creates a random port (used on the public side) and maps it to the clients (local) address and port.
So the router now knows that packets sent to the public address and the newly generated port belong to the local address and port.
Nobody can use this for something malicious.
Clients router sends UDP message containing the public address and the NAT generated port to the server.
The worst thing that can happen is that a man-in-the-middle attacker can read the data the client is sending. Due to it is only gamedata like positions and so on that is sent this is not a big problem while developing the basics.
Nobody can use this for something malicious.
Server receives the message and calls the callback described in 3. So the server sends to the public address and the NAT generated port of the client.
The worst thing that can happen is that a man-in-the-middle attacker can read the data the server is sending. Due to it is only gamedata like positions and so on that is sent this is not a big problem while developing the basics.
Nobody can use this for something malicious.
Same as 7. with the servers router and the servers local address and port.
Same as 8. with the servers router.
Client receives the UDP message of the server and calls a callback which processes the message contents.
Due to the local port of the client is bound to my application only nobody can use this for something malicious due to I simply ignore the contents if they are not from the real server.
Question
So is my assumption correct and I really don't need to secure the client from any attacks that will harm the clients in any way?

difference between socket failing with EOF and connection reset

For testing a networking application, I have written an asio port "proxy": it listens on a socket for the application client activity and sends all incoming packets to another socket where it is listened to by the application server, and back.
Now when either the application or the server disconnect for various reasons, the "proxy" usually gets an EOF but sometimes it receives a "connection reset".
Hence, the question: when does a socket fail with a "connection reset" error?
A TCP connection is "reset" when the local end attempts to send data to the remote end and the remote end answer with a packet with the RST flag set (instead of ACK). This almost always happens because the remote end doesn't know about any TCP connection that matches the remote&local addresses and remote&local port numbers. Possible reasons include:
The remote end has been rebooted
A state-tracking firewall somewhere in the path has been rebooted/changed/added/removed
A load balancer has incorrectly directed the TCP connection to a different node than the one it was supposed to go to.
The remote IP address has changed hands (the new owner doesn't know anything about TCP connections belonging to the old owner).
The remote end considers that the TCP connection has been closed already (but somehow the local end doesn't agree).
Note that if the remote end answers the initial (SYN) packet in a TCP connection with a RST packet, it is considered "Connection refused" instead of "Connection reset by peer".

TCP/IP basics: Destination port relevance

Ok this is kind of embarassing but I just have a rather "noob" question.
In a client server TCP communications, where my system is a client accessing a remote server at say Port XX, isnt the client opening a random port YY in its system to talk to remote port XX?
So when we code we do specify the destination port XX right?
For the client, the port YY itself is chosen when the socket is created, isnt it?
Is there anyway I could monitor/restrict/control any client talking to a particular server?(like say clients talking to servers at specific serving ports??)
Is there any IPTABLE rule or some firewall rule restricting the client?
Can this be done at all??
Are destination ports saved in the socket structures? If so where??
Thanks!
First, server side creates a listening socket, with the chain of socket(2), bind(2), and listen(2) calls, then waits for incoming client connection requests with the accept(2) call. Once a client connects (socket(2) and then connect(2) on the client side) and the TCP/IP stacks of the client and the server machines complete the three way handshake, the accept(2) returns new socket descriptor - that's the server's end of the connected socket. Both bind(2) on the server side, and connect(2) on the client side take server's address and port.
Now, the full TCP connection is described by four numbers - server address, server port, client address, and client port. The first two must obviously be known to the client prior to the connection attempt (otherwise, where do we go?). The client address and port, while could be specified explicitly with the bind(2), are usually assigned dynamically - the address is the IP address of the outgoing network interface, as determined by the routing table, and the port selected out of range of ephemeral ports.
The netstat(8) command shows you established connections. Adding -a flag lets you see listening sockets, -n flag disables DNS and service resolution, so you just see numeric addresses and ports.
Linux iptables(8) allows you to restrict where clients are allowed to connect to. You can restrict based on source and destination ports, addresses, and more.
You can get socket local binding with getsockname(2) call, remote binding is given by getpeername(2).
Hope this makes it a bit more clear.
Yes you can create a firewall rule to prevent outbound TCP connections to port XX. For example, some organizations prevent outbound TCP port 25, to prevent spam being sent from network PCs to remote SMTP servers.

Resources