From d6b2eaee49339b8d58fd6ad082073a4a7d8a8090 Mon Sep 17 00:00:00 2001 From: leafee98 Date: Sat, 3 Jan 2026 01:22:39 +0800 Subject: [PATCH] Add option -p, remove all non-ASCII charactor --- myip.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/myip.py b/myip.py index ce9f01a..761039f 100644 --- a/myip.py +++ b/myip.py @@ -3,9 +3,9 @@ import socket import socketserver import ipaddress import logging -from datetime import datetime +import argparse -# 日志配置(线程安全),按时间和级别输出到 stdout +# Configure logging (thread-safe), output time and level to stdout logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", @@ -18,7 +18,6 @@ class TCPServer6(socketserver.TCPServer): class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler): def log_response(self, status_code, client_ip, x_forwarded_for): - # 记录每次响应的日志 logging.info( "method=%s path=%s client_ip=%s x_forwarded_for=%s status=%d", self.command, @@ -29,48 +28,55 @@ class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler): ) def do_GET(self): - # 获取请求头中的 'X-Forwarded-For' 或 'Remote-Addr' + # Get 'X-Forwarded-For' header or remote address x_forwarded_for = self.headers.get('X-Forwarded-For') remote_addr = self.client_address[0] - # 客户端 IP 优先选择 X-Forwarded-For + # Prefer client IP from X-Forwarded-For if present client_ip = (x_forwarded_for.split(',')[0].strip() if x_forwarded_for else remote_addr) - # 将 IPv4-mapped IPv6 地址转换为纯 IPv4(例如 ::ffff:127.0.0.1 -> 127.0.0.1) + # Convert IPv4-mapped IPv6 addresses to plain IPv4 (e.g. ::ffff:127.0.0.1 -> 127.0.0.1) try: ip_obj = ipaddress.ip_address(client_ip) if isinstance(ip_obj, ipaddress.IPv6Address) and ip_obj.ipv4_mapped: client_ip = str(ip_obj.ipv4_mapped) except ValueError: - # 如果解析失败(非标准格式),尝试手工处理以防某些代理返回带方括号或端口 - # 移除 IPv6 方括号及端口(如 [::ffff:127.0.0.1]:8080) + # If parsing fails (non-standard format), attempt manual handling to cope with some proxies + # Remove IPv6 brackets and port (e.g. [::ffff:127.0.0.1]:8080) s = client_ip if s.startswith('[') and ']' in s: s = s.split(']', 1)[0].lstrip('[') if s.count(':') >= 2 and s.startswith('::ffff:'): - # 处理可能带端口的情况 + # Handle possible port by taking the last segment s = s.split(':')[-1] client_ip = s - # 发送响应 + # Send response status_code = 200 self.send_response(status_code) self.send_header("Content-type", "text/plain") self.end_headers() self.wfile.write(client_ip.encode()) - # 在响应后记录日志 + # Log after responding try: self.log_response(status_code, client_ip, x_forwarded_for) except Exception: logging.exception("Failed to log response") +def parse_args(): + parser = argparse.ArgumentParser(description="Simple IPv6-capable HTTP server that returns client IP.") + parser.add_argument("-p", "--port", type=int, default=8080, help="Port to listen on (default: 8080)") + return parser.parse_args() + if __name__ == "__main__": - PORT = 8080 - # 对于 AF_INET6 使用四元组绑定所有 IPv6 地址 + args = parse_args() + PORT = args.port + + # For AF_INET6 bind to all IPv6 addresses using a 4-tuple server_address = ("::", PORT, 0, 0) with TCPServer6(server_address, MyHTTPRequestHandler) as httpd: - # 可选:在绑定前设置 IPV6_V6ONLY,若需要同时接受 IPv4 映射地址可设为 0 + # Optionally set IPV6_V6ONLY. Set to 0 to accept IPv4-mapped addresses as well. try: httpd.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) except Exception: