Python HTTPServer 只响应我?

Python HTTPServer that only responds to me?

提问人:Kenglaze 提问时间:10/9/2023 更新时间:10/9/2023 访问量:43

问:

我实现了一个python http服务器,它只响应获取请求,以远程向我提供数据图,向我展示我的光伏系统在家中做什么。我注意到一些来自不属于我自己的 IP 地址的失败请求,并希望将其锁定一点以拒绝来自非我专用计算机的连接。

示例:如果有一种方法可以仅响应源自我 iPhone 的 MAC 地址的 GET 请求,并且不提供任何响应,因此其他人无法检测到该服务,那将是理想的选择。

问题 2:如果我使用 ctrl-c 退出此脚本,此代码是否会在运行某些内容时保持运行状态,或者守护程序是否会在我退出脚本时负责停止服务器?

这是我当前使用的代码。您可能对锁定此事物的任何想法、评论和建议都很棒!

from http.server import HTTPServer, BaseHTTPRequestHandler, ThreadingHTTPServer
import threading

def load_binary(filename):
    with open(filename, 'rb') as file_handle:
        return file_handle.read()
        
class MyRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        if self.path == '/':
            os.system('python3 /home/pi/Plot_Generator_0_2.py')
            mimetype='image/png'
            self.send_response(200, 'OK')
            self.send_header('Content-type',mimetype)
            self.end_headers()
            self.wfile.write(load_binary('plot_image.png'))

if currentOS != "Windows":
    server = ThreadingHTTPServer(('192.168.0.122', 5555), MyRequestHandler)
    server_thread = threading.Thread(target=server.serve_forever)
    server_thread.daemon = True
    server_thread.start()
安全性 python 多线程 httpserver mac-address

评论


答:

0赞 tr0yspradling 10/9/2023 #1

第1项质询

在处理应用程序级协议(如 HTTP)时,套接字通常不会公开较低级别的网络详细信息,例如 MAC 地址。对 TCP/IP 标头的访问受到限制,因此在此层无法直接进行 MAC 过滤。

为了捕获这些细节,需要使用专门的软件,如数据包捕获库(例如,WinPCap、libpcap)在网络堆栈的较低级别运行。如果不仔细实施,这可能会带来巨大的复杂性和潜在的漏洞。它还使软件堆栈复杂化,使管理和解决问题更具挑战性。

选项

请记住,这些示例没有经过测试,也没有用于生产,不应这样使用。如果您计划将此应用程序投入生产,请使用现有框架。

  1. IP 允许列表(客户端需要静态 IP)
class MyRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        client_ip, _ = self.client_address
        if client_ip not in ['192.168.0.122', '192.168.0.123', '127.0.0.1']:
            self.send_error(403)
            return
        ...
  1. HTTP 基本身份验证
class MyRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.headers.get('Authorization') == 'Basic ' + str(b64encode(('username:password').encode('utf-8')).decode('utf-8')):
            # Your existing code for handling GET requests
        else:
            self.send_response(401)
            self.send_header('WWW-Authenticate', 'Basic realm=\"Authorization required\"')
            self.end_headers()
            self.wfile.write(b'Authorization required.')

如果选择此路由,则应启用 HTTPS。否则,这些信息将是纯文本的,不安全。


第2项质询

使用 ctrl-c 退出应该足以终止服务器及其所有线程,而不会让任何线程保持运行。

评论

0赞 Kenglaze 10/9/2023
我非常感谢这些解释和例子。我将尝试实现您在启用 HTTPS 的情况下提供的选项 2,看看效果如何。旁注,我更改了代码,使其仅响应 ip-address:64XXX/plot,而没有其他响应,因此端口号不太可能成为扫描的一部分,并且他们只会看到该特定请求的返回,而不使用“super().do_GET()”,否则仍将提供显示服务器存在的响应。我可以做任何其他简单的事情来减少“可见”吗?
0赞 tr0yspradling 10/9/2023
另一个想法是将 python 服务器放在带有 ACL 的网络 VLAN 上,以仅允许批准的客户端。这将需要支持 VLAN 的路由器/交换机。
0赞 Kenglaze 10/11/2023
我很欣赏你的评论!我可以看到这将如何在本地网络上提供一些隔离,但是我担心的是来自WAN的请求,当我在外出时,我的手机会发出请求,使我看起来与恶意请求无法区分。所有外部请求仍然必须通过WAN并路由到我的服务器,即使它位于自己的VLAN上。还是我的建议中遗漏了什么?
0赞 tr0yspradling 10/11/2023
是的,那行不通。如果您要离开LAN,则完全不可能进行MAC过滤,并且IP允许列表也不是一个好的解决方案,因为您只能从已知网络进行连接。这是另外两个选项(ssh 代理或端口敲击): security.stackexchange.com/a/153211
1赞 mighty_mike 10/9/2023 #2

您无法从 HTTP 请求中获取 MAC 地址,因为此信息不会传递到 HTTP 运行的应用程序层。

但是,如果您希望识别或区分设备,请考虑使用 Cookie、会话或令牌来实现此目的。

对于第二个问题:是的,使用 ctrl-c 退出脚本也会停止服务器,并且退出后此脚本不会有任何运行。