我计划将服务器合并到我正在开发的应用程序中(所传输的数据都不会敏感)。我在路由器上设置了指向网络服务器的端口转发。以下是服务器端代码的片段:
import time
import threading
import socketserver
import ssl
class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
def handle(self):
# Each new request is handled by this function.
data = str(self.request.recv(4096), 'utf-8')
print('Request received on {}'.format(time.ctime()))
print('{} wrote: {}'.format(self.client_address[0], data))
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'utf-8')
self.request.sendall(response)
class TLSTCPServer(socketserver.TCPServer):
def __init__(self, server_address, request_handler_class, certfile, keyfile, ssl_version=ssl.PROTOCOL_TLSv1_2,
bind_and_activate=True):
socketserver.TCPServer.__init__(self, server_address, request_handler_class, bind_and_activate)
self.certfile = certfile
self.keyfile = keyfile
self.ssl_version = ssl_version
def get_request(self):
newsocket, fromaddr = self.socket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile=self.certfile,
keyfile=self.keyfile,
ssl_version=self.ssl_version)
return connstream, fromaddr
class ThreadedTCPServer(socketserver.ThreadingMixIn, TLSTCPServer):
pass
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 6001
# Creates a server that handles each request on a separate thread. "cert.pem" is the TLS certificate and "key.pem"
# is the TLS private key (kept only on the server).
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler, "cert.pem", "key.pem")
ip, port = server.server_address
print('Started server\n')
server.serve_forever()
这是客户端代码:
import socket
import time
import ssl
HOST = 'localhost' # This should be the server's public IP when used in production code
PORT = 6001
data = 'Hello!'
start_time = time.time()
try:
# Connect to server and send data
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(sock,
ca_certs="cert.pem",
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1_2)
ssl_sock.connect((HOST, PORT))
ssl_sock.sendall(data.encode())
# Receive data from the server and shut down
received = ssl_sock.recv(4096)
elapsed_tie = round(time.time() - start_time, 2)
print("Sent: {}".format(data))
print("Received: {}".format(received.decode('utf-8')))
print("Elapsed: {}s \n".format(elapsed_tie))
ssl_sock.close()
except Exception as e:
print(format(e))
请注意,在Mac或Linux终端中使用此命令生成cert.pem
和key.pem
:openssl req -newkey rsa:4096 -nodes -sha512 -x509 -days 3650 -nodes -out cert.pem -keyout key.pem
服务器使用TLS来保护数据,并在不同的线程上处理请求。为每个请求完成的计算量相对较小,因为它主要包括在每次请求时向数据库读取和写入少量数据。
我主要担心的是,恶意行事的人可以弄清楚服务器的公共IP地址是什么并执行DDOS攻击。我认为缓解这种情况的一种方法是拒绝来自同一客户端地址的过于频繁的请求。还有其他方法可以减轻此类攻击吗?另外,在Python中运行安全服务器是一个好主意还是我应该在其他地方寻找?提前谢谢。
---编辑---
我在考虑检查同一个用户是否在一定时间内发出太多请求。由于请求是在计时器上(例如,5秒),因此任何更频繁的请求都被认为是可疑的。只要传入的请求不会使路由器的带宽饱和,理论上我就应该拒绝某些请求。但是,如果多台计算机从同一网络发出请求,我只能查看传入的请求'公共IP地址,因为我可能会拒绝完全有效的请求。提出请求的机器是否有可识别的ID?
答案 0 :(得分:1)
当遭遇DDoS攻击时,为时已晚。数据包到达您的服务器并填满您的管道。无论你做什么,他们已经在那里 - 他们中的许多人。您可以丢弃它们,但其他人仍然无法联系到您。
DDoS保护必须由能够决定数据包是否为恶意的人员在上行链路上完成。这是一项神奇的操作,Cloudflare或Akamai等公司会让您付出很多代价。
另一种可能性是在攻击期间将DNS条目更改为其他位置。这真是一件好事,因此您的客户知道您的网站正在维护中,很快就会回来#34;