The question is the title.
But I'd like to describe my problem so that someone can suggest an alternative solution.
I know that when the client sends a message on a socket to 12.34.56.78:40, the router on the client's side sets a rule for some time that any data received from the 12.34.56.78:40 is allowed and will be sent to the client machine on the network.
so the problem I have is that the client is sending to the server on some port but the server needs to reply using a different socket (thus a different port). but ofcourse the server's ip didnt change.
so that was my first idea of solving the problem
spoof the outgoing port
Multiple sockets can bind to the same port, and thus send packets with the same source port number, if the each socket sets the SO_REUSEPORT socket option. See the SO_REUSEPORT socket option and the difference between SO_REUSEADDR and SO_REUSEPORT.
Related
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?
I need to write an application in Node.js which sends some UDP packets to a given IP address and Port as well as listening for UDP packets from the same IP and Port.
Other examples i have seen all seem to mention a Client and Server architecture with one side sending and the other receiving. I need to do both in one app.
My question is: Can i send and receive on the same socket or should i have one for each as below?
const Send= dgram.createSocket('udp4');
const Recieve= dgram.createSocket('udp4');
Thanks
You only need one socket - it's possible to both send and receive on the same one.
However to be able to receive the socket will need to be "bound" to a local port using socket.bind().
I'm writting a program that simulates nodes in network. Every node is listening to some port on local for incoming requests. If a request is received it replies to sender of the request. The reply is sent after a socket is created associated with the address of the sender of the request. Since sender is using some port on localhost and has used bind to listen to id, trying to bind to the same port with an other process results in a messages that states that the port is already taken (bound).
How should I solve this in order to be able to simulate server/client on the same machine? I am using UDP protocol for this program.
You solve this by using different ports for client and server interaction. A useful example would be how client and server interact during DHCP. The client sends requests via UDP on port 67 and the server sends responses back via UDP on port 68.
I am using a tcp socket on linux to listen for incoming tcp connections. the socket is blocking type.
I would like to find out what client is trying to connect to my socket before calling accept(). More specifically, I want to know the source IP and port.
Now, I have done some reading, and found people saying that this is not possible because the source IP address is not known (yet). I don't understand this. if a client notified the server that it wants to connect then it must have sent a SYN packet, which contains the information I want, right?
(source)
Obtaining the source IP and port of an INADDR_ANY client socket before the TCP three-way handshake?
Perhaps they were referring to the client side.
As a server, I can select() or poll() the file descriptor to know how many clients want to connect, why can't I get their ip addresses and ports before accept()ing the connection?
I am sorry, my knowledge of networking is not so rich.
Thank you.
It is the accept that returns a new socket id for the new connection that got established. If accept fails there is no connections anyways.
And with new socket on successful accept you can use getpeername to determine the client details.
select or poll will only notify activity on socket and not give any more details. You need to depend on accept to check if connection is successful or not
Thanks everyone for your answers. I figured out a workaround to my problem. so I figured I'd post it as a solution to my own question.
It is possible to use iptables and netfilter_queue under linux and filter out the SYN packets. One can then read the needed information from the packet and re-insert it into the stack without "accept"ing it!
I have tried this and it works. :)
Thanks, everyone, for your help.
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.