Timeout SSL handshake - python

I'm trying to incorporate TimeoutMixin in a protocol over SSL. However, when the timeout occurs and it makes a call to the transport.loseConnection() nothing happens. I think this is related to this code in TLSMemoryBIOProtocol:
def _shutdownTLS(self):
"""
Initiate, or reply to, the shutdown handshake of the TLS layer.
"""
try:
shutdownSuccess = self._tlsConnection.shutdown()
except Error:
# Mid-handshake, a call to shutdown() can result in a
# WantWantReadError, or rather an SSL_ERR_WANT_READ; but pyOpenSSL
# doesn't allow us to get at the error. See:
# https://github.com/pyca/pyopenssl/issues/91
shutdownSuccess = False
self._flushSendBIO()
if shutdownSuccess:
# Both sides have shutdown, so we can start closing lower-level
# transport. This will also happen if we haven't started
# negotiation at all yet, in which case shutdown succeeds
# immediately.
self.transport.loseConnection()
The issue is that the time-out is happening before the handshaking can occur. On the server side it has a port open listening for connections but the server is frozen and can't do the proper handshaking. That code snippet looks like it fails to do the TLS shutdown and then does nothing.
My question is:
How do I set a timeout on the SSL handshaking? If the handshaking doesn't happen in a reasonable amount of time, how do drop the connection properly? Also, is there anything wrong with the above snippet being changed to drop the underlying lower-level connection regardless of the severing of the TLS connection? (just doing nothing and hanging indefinitely doesn't seem like the right approach)
EDIT:
The failure of the call to loseConnection seems to happen if any data is sent before and if nothing is sent than it seems to work properly.

loseConnection is the API for an orderly connection shutdown. If you want to terminate the connection abruptly, abortConnection is the API for you.

Related

Paho MQTT (Python) - when to call client.loop_stop() during disconnection?

I'm writing a simple Python client using Paho MQTT to communicate with mosquitto. I'm running into some issues with client.disconnect() and more specifically client.loop_stop().
According to the Paho docs, loop_start() is used to start up a threaded network loop. I've found that the most reliable way to call this is immediately after calling client.connect(). Apparently calling it just prior can have some unexpected effects. Anyway, for me this works fine.
The issue is around when I call client.loop_stop() around the time I wish to disconnect. Some online tutorials show that the best place to call this is in the on_disconnect handler, to be sure that the disconnection has fully completed, and so that any pending subscription or unsubscription attempts have been fully handled by the broker. This appears to work, but if I then attempt to reconnect (by a call to client.connect()) then the connection attempt does not work correctly - the client state gets stuck midway through, and the mosquitto broker only reports the following:
1642374165: New connection from 127.0.0.1:39719 on port 1883.
And nothing else. The connection has not worked. I'm not sure if the Broker is waiting for something from the Client (most likely?), or the Client has sent bad data to the Broker and triggered some kind of issue, but whatever the case, the connection is not valid.
If I move the loop_stop() call to just prior to the call to client.disconnect(), I get much more reliable behaviour, and the broker shows a proper subsequent connection attempt:
1642375893: New connection from 127.0.0.1:38735 on port 1883.
1642375893: New client connected from 127.0.0.1:38735 as client0 (p2, c0, k60).
1642375893: No will message specified.
1642375893: Sending CONNACK to client0 (1, 0)
However I understand that this may cause other issues - in particular, the disconnection may occur before any pending subscription or unsubscription requests have been fully processed, since the network loop is terminated before the disconnection is performed.
What I'd like to know is what's the official word on how to do a clean disconnection and terminate the network loop thread properly, without resorting to arbitrary time.sleep() delays to give things enough time to work themselves out.

How to know if the remote tcp device is powered off

In my GO code, I am establishing a TCP connection as below:
conn, err1 := net.Dial("tcp", <remote_address>)
if err1 == nil {
buf := make([]byte, 256)
text, err := conn.Read(buf[:])
if err == io.EOF {
//remote connection close handle
fmt.Println("connection got reset by peer")
panic(err)
}
}
To simulate the other end, I am running a python script on a different computer, which opens a socket and sends some random data to the socket above lines of codes are listening to. Now my problem is, when I am killing this python code by pressing ctrl+C, the remote connection closed event is recognised finely by above code and I get a chance to handle that.
However, if I simply turn off the remote computer (where the python script is running) my code doesn't get notified at all.
In my case, the connection should always be opened and should be able to send the data randomly, and only if the remote machine gets powered off, my GO code should get notified.
Can someone help me in this scenario, how would I get notification when the remote machine hosting the socket itself gets powered off? How would I get the trigger remotely in my GO code?
PS - This seems to be a pretty common problem in real time, though not in the testing environment.
There is no way to determine the difference between a host that is powered off and a connection that has been broken, so you treat them the same way.
You can send a heartbeat message on your own, and close the connection when you reach some timeout period between heartbeat packets. The timeout can either be set manually by timing the packets, or you can use SetReadDeadline before each read to terminate the connection immediately when the deadline is reached.
You can also use TCP Keepalive to do this for you, using TCPConn.SetKeepAlive to enable it and TCPConn.SetKeepAlivePeriod to set the interval between keepalive packets. The time it takes to actually close the connection will be system dependent.
You should also set a timeout when dialing, since connecting to a down host isn't guaranteed to return an ICMP Host Unreachable response. You can use DialTimeout, a net.Dialer with the Timeout parameter set, or Dialer.DialContext.
Simply reading through the stdlib documentation should provide you with plenty of information: https://golang.org/pkg/net/
You need to add some kind of heartbeat message. Then, looking at GO documentation, you can use DialTimeout instead of Dial, each time you receive the heartbeat message or any other you can reset the timeout.
Another alternative is to use TCP keepalive. Which you can do in Python by using setsockopt, I can't really help you with GO but this link seems like a good description of how to enable keepalive with it:
http://felixge.de/2014/08/26/tcp-keepalive-with-golang.html

Sleep after ZMQ connect?

In a ROUTER-ROUTER setup, after I connect one ROUTER socket to another, if I don't sleep (for say 0.1s or so) after I connect() to the other ROUTER socket, the send() usually doesn't go through (although it sometimes does, by chance).
Is there a way to make sure I am connected before I send?
Why aren't the send()s queued and properly executed until the connection is made?
Also, this is not about whether the server on the other end is alive but rather that I send() too soon after I connect() and somehow it fails. I am not sure why.
Is there a way to make sure I am connected before I send?
Not directly. The recommended approach is to use something like the Freelanch Protocol and keep pinging until you receive a response. If you stop receiving responses to your pings you should consider yourself disconnected.
Why aren't the send()s queued and properly executed until the connection is made?
A router cannot send a message to a peer until both sides have completed an internal ZeroMQ handshake. That's just the way it works, since the ROUTER requires the ID of its peer in order to "route". Apparently sleeping for .1sec is the right amount of time on your dev system. If you need the ability to connect and then send without sleeping or retrying, then you need to use a different pattern.
For example, with DEALER-ROUTER, a DEALER client can connect and immediately send and ZeroMQ will queue the message until it is delivered. The reason the works is that the DEALER does not require the ID of the peer - since it does not "route". When the ROUTER server receives the message, that handshake is already complete so it can respond right away without sleeping.

Close inactive connections in Twisted

I'm running a Twisted server with the LineReceiver protocol. Sometimes clients will disconnect silently, so Twisted keeps the connection open. And because the server doesn't send anything unless requested of it, there's never a TCP timeout. In other words, some connections are never closed server-side.
How can I have Twisted close a connection that's been inactive for a few hours?
You can schedule timed events using reactor.callLater. Based on this, there's a helper for adding timeouts to protocols, twisted.protocols.policies.TimeoutMixin.
Another approach is to use TCP keep-alives, which you can enable using the transport's setTcpKeepAlive method.
And another approach is to use application-level keep-alives. Essentially send a ''noop'' once in a while. It doesn't need a response. If the connection has been lost, the extra data in the send buffer will cause the TCP stack to eventually notice.
See also the FAQ entry.

Does a pop3 connection timeout?

I am using python poplib.
Does a POP3 connection timeout after a period of inactivity? Is there a way to set this timeout? Would such a timeout cause emails flagged for deletion to be deleted as if quit() had been called?
The only timeout I see mentioned refers to the connection-attempt timeout
class poplib.POP3(host[, port[, timeout]])
My POP3.quit() call is throwing a poplib.error_proto exception with the message "timed out" and I am wondering if the connection will ever timeout on its own.
Does a POP3 connection timeout after a period of inactivity?
This mostly depends on the server software on the other end. Some socket libraries may let you specify a local timeout. The connection will timeout at whatever time is the shortest between the local and the remote timeout.
Is there a way to set this timeout?
Unless you control the server software settings (e.g. you run your own server), you can't change the remote timeout.
Would such a timeout cause emails flagged for deletion to be deleted as if quit() had been called?
Timeout behavior is usually the same as manually closing the socket (with or without shutdown). If you don't send the quit command, messages won't be deleted from the server.
POP3 is sort of transactional. So if you download and delete a message from the server, it will not be effective until you close the connection gracefully. The POP3.quit() method has an insightful description about it. The magic word is commit.
The connection timeout is usually a server setting and, of course, when the server times out the connection it is considered a rollback.
Yes a POP3 socket will eventually time out. Looking here you pass the timeout in the constructor.
http://docs.python.org/library/poplib.html
class poplib.POP3(host[, port[, timeout]])

Categories