Sending a reset in TCP/IP Socket connection - python

I am using python’s socket.py to create a connection to an ftp-server. Now I want to reset the connection (send a RST Flag) and listen to the response of the ftp-server. (FYI using socket.send('','R') does not work as the OS sends FIN flag instead of RST.)

Turn the SO_LINGER socket option on and set the linger time to 0 seconds. This will cause TCP to abort the connection when it is closed, flush the data and send a RST. See section 7.5 and example 15.21 in UNP.
In python:
def client(host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.connect((host, port))
l_onoff = 1
l_linger = 0
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
struct.pack('ii', l_onoff, l_linger))
# send data here
s.close()

If you want to implement your own behavior over connections I think you should try using Scapy. It is a really useful library/tool. It lets you play with IP/TCP/UDP/ICMP packages.

To send an RST on a TCP connection, set the SO_LINGER option to true with a zero timeout, then close the socket. This resets the connection. I have no idea how to do that in Python, or indeed whether you can even do it.

Related

How to make a socket server that only accepts one connection?

I write a TCP server using Python. I want the server
only accept on client connection.
I use the listen function
listen(1)
but the server still can accepts more than one connection.
From the documentation:
If backlog is specified, it must be at least 0 (if it is lower, it is set to 0); it specifies the number of unaccepted connections that the system will allow before refusing new connections.
So if you use listen(1) you allow one unaccepted connection. If you want to allow no unaccepted connections, you must use listen(0).
If you want only one connection, pleae don't use loop for socket.accept() in- connections.
demo code:
#!/usr/bin/python
import time
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_addr = ('127.0.0.1', 8080)
server.bind(server_addr)
server.listen(1)
print("listening on {}".format(server_addr))
client, client_addr = server.accept()
for i in range(10):
client.send("num: {}\n".format(i))
time.sleep(1)
raw_input('')

How to limit the number of connections to a socket and trigger timeout on client (Python)

How can I set a limit on the number of connections that a server socket can accept at once? I want to be able to set a max number of connections, and then once that limit is reached, any further attempts from clients to connect will result in a timeout. So far, I have tried something like this for the server:
sock = socket.socket()
sock.setblocking(0)
sock.bind(address)
sock.listen(0)
connections = []
while True:
readable, writable, exceptional = select.select([sock], [], [])
if readable and len(connections) < MAX_CONNECTIONS:
connection, client_address = s.accept()
connections.append(connection)
# Process connection asynchronously
and for the client:
try:
sock = socket.create_connection(self.address, timeout=TIMEOUT)
sock.settimeout(None)
print "Established connection."
except socket.error as err:
print >> sys.stderr, "Socket connection error: " + str(err)
sys.exit(1)
# If connection successful, do stuff
Because of the structure of the rest of the program, I have chosen to use a non-blocking socket on the server and I do not wish to change this. Right now, the clients are able to connect to the server, even after the limit is reached and the server stops accepting them. How do I solve this? Thanks.
I believe there might be a slight misunderstanding of select() at play here. According to the manpage, select() returns file descriptors that are "ready for some class of IO operation", where ready means "it is possible to perform a corresponding IO operation without blocking".
The corresponding IO operation on a listening socket is accept(), which can only be performed without blocking if the OS already made the full TCP handshake for you, otherwise you might block waiting for the client's final ACK, for instance.
This means that as long as the listening socket is open, connections will be accepted by the OS, even if not being handled by the application.
If you want to reject connections after a set number, you have basically two options:
simply accept and close directly after accepting.
close the listening socket upon reaching the limit and reopen when done.
The second option is more convoluted and requires use of the SO_REUSEADDR option, which might not be the right thing in your case. It might also not work on all OSs, though it does seem to work reliably on Linux.
Here's a quick sketch of the second solution (since the first is pretty straightforward).
def get_listening_socket():
sock = socket.socket()
sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 5555))
sock.listen(0)
return sock
sock = get_listening_socket()
LIMIT = 1
conns = {sock}
while True:
readable, writable, exceptional = select.select(conns, [], [])
if sock in readable: # new connection on the listening socket
conn, caddr = sock.accept()
conns.add(conn)
if len(conns) > LIMIT: # ">" because "sock" is also in there
conns.remove(sock)
sock.close()
else: # reading from an established connection
for c in readable:
buf = c.recv(4096)
if not buf:
conns.remove(c)
sock = get_listening_socket()
conns.add(sock)
else:
print("received: %s" % buf)
You may, however, want to rethink why you'd want to do this in the first place. If it's only about saving some memory on the server, than you might be over-optimizing and should be looking into syn-cookies instead.

Client Python close my TCP connection without socket.close()

I am developing a TCP client on Python, and I have the next problem. I connect with the server, I send it some data, it response me with the data expected but after this the my own application (client) send a [FIN, ACK] (checked with wireshark). Here is my client app:
try:
sock = socket(AF_INET, SOCK_STREAM)
sock.bind((my_ip,my_port))
sock.connect((sendAddress,sendPort))
sock.send(joinRequest)
joinResponse = sock.recv(18)
print joinResponse
except socket.timeout:
sock.close()
This is the default behavior of SocketServer, accept a connection, get the request, and then close the connection.
The simple way will be to use while loop to keep it connected, You can also use sock.settimeout to tune the timeout

python sockets: make sure that TCP packets are send before closing connection

I am working with a relay that is controlled via TCP. As far as I understood the following code is supposed to work:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.200', 17494))
s.send(chr(101))
s.close()
However, I noticed that the socket gets closed before the package is actually send, and the relay does not do anything. As dirty solution I now put a sleep statement before closing the connection and it works properly.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.200', 17494))
s.send(chr(101))
time.sleep(0.01)
s.close()
Is there something more clever one can do to ensure that the package got actually send before closing the connection?
You could set the SO_LINGER option using s.setsockopt. The linger option makes the socket wait (internally) and close only after sending all the pending data upto the specified timeout value. Something like:
linger_enabled = 1
linger_time = 10 #This is in seconds.
linger_struct = struct.pack('ii', linger_enabled, linger_time)
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, linger_struct)

Python: Binding Socket: "Address already in use"

I have a question regarding client socket on TCP/IP network. Let's say I use
try:
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except socket.error, msg:
sys.stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(1)
try:
comSocket.bind(('', 5555))
comSocket.connect()
except socket.error, msg:
sys.stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(2)
The socket created will be bound to port 5555. The problem is that after ending the connection
comSocket.shutdown(1)
comSocket.close()
Using wireshark, I see the socket closed with FIN,ACK and ACK from both sides, I can't use the port again. I get the following error:
[ERROR] Address already in use
I wonder how can I clear the port right away so that next time I still can use that same port.
comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
setsockopt doesn't seem to be able to resolve the problem
Thank you!
Try using the SO_REUSEADDR socket option before binding the socket.
comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Edit:
I see you're still having trouble with this. There is a case where SO_REUSEADDR won't work. If you try to bind a socket and reconnect to the same destination (with SO_REUSEADDR enabled), then TIME_WAIT will still be in effect. It will however allow you to connect to a different host:port.
A couple of solutions come to mind. You can either continue retrying until you can gain a connection again. Or if the client initiates the closing of the socket (not the server), then it should magically work.
Here is the complete code that I've tested and absolutely does NOT give me a "address already in use" error. You can save this in a file and run the file from within the base directory of the HTML files you want to serve. Additionally, you could programmatically change directories prior to starting the server
import socket
import SimpleHTTPServer
import SocketServer
# import os # uncomment if you want to change directories within the program
PORT = 8000
# Absolutely essential! This ensures that socket resuse is setup BEFORE
# it is bound. Will avoid the TIME_WAIT issue
class MyTCPServer(SocketServer.TCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = MyTCPServer(("", PORT), Handler)
# os.chdir("/My/Webpages/Live/here.html")
httpd.serve_forever()
# httpd.shutdown() # If you want to programmatically shut off the server
According to this link
Actually, SO_REUSEADDR flag can lead to much greater consequences:
SO_REUSADDR permits you to use a port that is stuck in TIME_WAIT, but
you still can not use that port to establish a connection to the last
place it connected to. What? Suppose I pick local port 1010, and
connect to foobar.com port 300, and then close locally, leaving that
port in TIME_WAIT. I can reuse local port 1010 right away to connect
to anywhere except for foobar.com port 300.
However you can completely avoid TIME_WAIT state by ensuring that the remote end initiates the closure (close event). So the server can avoid problems by letting the client close first. The application protocol must be designed so that the client knows when to close. The server can safely close in response to an EOF from the client, however it will also need to set a timeout when it is expecting an EOF in case the client has left the network ungracefully. In many cases simply waiting a few seconds before the server closes will be adequate.
I also advice you to learn more about networking and network programming. You should now at least how tcp protocol works. The protocol is quite trivial and small and hence, may save you a lot of time in future.
With netstat command you can easily see which programs ( (program_name,pid) tuple) are binded to which ports and what is the socket current state: TIME_WAIT, CLOSING, FIN_WAIT and so on.
A really good explanation of linux network configurations can be found https://serverfault.com/questions/212093/how-to-reduce-number-of-sockets-in-time-wait.
In case you face the problem using TCPServer or SimpleHTTPServer,
override SocketServer.TCPServer.allow_reuse_address (python 2.7.x)
or socketserver.TCPServer.allow_reuse_address (python 3.x) attribute
class MyServer(SocketServer.TCPServer):
allow_reuse_address = True
server = MyServer((HOST, PORT), MyHandler)
server.serve_forever()
You need to set the allow_reuse_address before binding. Instead of the SimpleHTTPServer run this snippet:
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler, bind_and_activate=False)
httpd.allow_reuse_address = True
httpd.server_bind()
httpd.server_activate()
httpd.serve_forever()
This prevents the server from binding before we got a chance to set the flags.
As Felipe Cruze mentioned, you must set the SO_REUSEADDR before binding. I found a solution on another site - solution on other site, reproduced below
The problem is that the SO_REUSEADDR socket option must be set before
the address is bound to the socket. This can be done by subclassing
ThreadingTCPServer and overriding the server_bind method as follows:
import SocketServer, socket
class MyThreadingTCPServer(SocketServer.ThreadingTCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
I found another reason for this exception.
When running the application from Spyder IDE (in my case it was Spyder3 on Raspbian) and the program terminated by ^C or an exception, the socket was still active:
sudo netstat -ap | grep 31416
tcp 0 0 0.0.0.0:31416 0.0.0.0:* LISTEN 13210/python3
Running the program again found the "Address already in use"; the IDE seems to start the new 'run' as a separate process which finds the socket used by the previous 'run'.
socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
did NOT help.
Killing process 13210 helped.
Starting the python script from command-line like
python3 <app-name>.py
always worked well when SO_REUSEADDR was set to true. The new Thonny IDE or Idle3 IDE did not have this problem.
socket.socket() should run before socket.bind() and use REUSEADDR as said
I know you've already accepted an answer but I believe the problem has to do with calling bind() on a client socket. This might be OK but bind() and shutdown() don't seem to play well together. Also, SO_REUSEADDR is generally used with listen sockets. i.e. on the server side.
You should be passing and ip/port to connect(). Like this:
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.connect(('', 5555))
Don't call bind(), don't set SO_REUSEADDR.
For me the better solution was the following. Since the initiative of closing the connection was done by the server, the setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) had no effect and the TIME_WAIT was avoiding a new connection on the same port with error:
[Errno 10048]: Address already in use. Only one usage of each socket address (protocol/IP address/port) is normally permitted
I finally used the solution to let the OS choose the port itself, then another port is used if the precedent is still in TIME_WAIT.
I replaced:
self._socket.bind((guest, port))
with:
self._socket.bind((guest, 0))
As it was indicated in the python socket documentation of a tcp address:
If supplied, source_address must be a 2-tuple (host, port) for the socket to bind to as its source address before connecting. If host or port are ‘’ or 0 respectively the OS default behavior will be used.
another solution, in development environment of course, is killing process using it, for example
def serve():
server = HTTPServer(('', PORT_NUMBER), BaseHTTPRequestHandler)
print 'Started httpserver on port ' , PORT_NUMBER
server.serve_forever()
try:
serve()
except Exception, e:
print "probably port is used. killing processes using given port %d, %s"%(PORT_NUMBER,e)
os.system("xterm -e 'sudo fuser -kuv %d/tcp'" % PORT_NUMBER)
serve()
raise e
I think the best way is just to kill the process on that port, by typing in the terminal fuser -k [PORT NUMBER]/tcp, e.g. fuser -k 5001/tcp.
I had the same problem and I couldn't find any other solution (reuse options didn't work) except restarting Raspberry Pi each time. Then I found a workaround;
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.close()
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.connect(('', 5555))
This means, define socket first, close it, then define again, so you can use the same port if it is stuck.

Categories

Resources