pythonでTCPサーバを立てるのに SocketServer.TCPServer
を使った例をよく見かけます。
import SocketServer
HOST, PORT = "", 12345
class SampleHandler(SocketServer.BaseRequestHandler):
def handle(self):
client = self.request
address = self.client_address[0]
client.send("May I ask your name? ")
name = client.recv(80).strip()
self.request.send("Welcome %s from %s\n" % (name, address))
if __name__ == "__main__":
server = SocketServer.TCPServer((HOST, PORT), SampleHandler)
server.serve_forever()
ですが、これですと1時点に1接続しか処理できず、処理中に新たな接続要求が来た場合には前の処理が終了するまで待たされてしまいます。
この SocketServer.TCPServer
を SocketServer.ThreadingTCPServer
に変えるだけで複数接続を同時処理できるようになります。
if __name__ == "__main__":
server = SocketServer.ThreadingTCPServer((HOST, PORT), SampleHandler)
server.serve_forever()
ただし、使用ソケット数が増えてしまうので、iptablesで接続数上限を設定したり、sysctlでTIME_WAIT時間を短くするなどの対処も行うといいでしょう。上限や時間はサービスに合わせて調整してください。
-A INPUT -p tcp -m tcp --dport 12345 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 15 --connlimit-mask 32 --connlimit-saddr -j REJECT --reject-with tcp-reset
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
また、スクリプトを再起動するとアドレス使用中エラーになるなら、次のようにスクリプト側でアドレス再利用設定をしておくといいでしょう。
import SocketServer
import socket
HOST, PORT = "", 12345
class SampleHandler(SocketServer.BaseRequestHandler, object):
def handle(self):
client = self.request
address = self.client_address[0]
client.send("May I ask your name? ")
name = client.recv(80).strip()
self.request.send("Welcome %s from %s\n" % (name, address))
class SampleServer(SocketServer.ThreadingTCPServer, object):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
if __name__ == "__main__":
server = SampleServer((HOST, PORT), SampleHandler)
server.serve_forever()
ThreadingTCPServerを使ってCTF問題サーバを2つほど運用してみました。
SECCON CTF 2014 winter online qualifications
Choose the number : https://github.com/shiracamus/seccon2014/blob/master/number/number.py
Let's disassemble : https://github.com/shiracamus/seccon2014/blob/master/disassemble/disassemble.py