Add option -p, remove all non-ASCII charactor

This commit is contained in:
leafee98 2026-01-03 01:22:39 +08:00
parent a7a97488bb
commit d6b2eaee49

34
myip.py
View file

@ -3,9 +3,9 @@ import socket
import socketserver import socketserver
import ipaddress import ipaddress
import logging import logging
from datetime import datetime import argparse
# 日志配置(线程安全),按时间和级别输出到 stdout # Configure logging (thread-safe), output time and level to stdout
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s", format="%(asctime)s %(levelname)s %(message)s",
@ -18,7 +18,6 @@ class TCPServer6(socketserver.TCPServer):
class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler): class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def log_response(self, status_code, client_ip, x_forwarded_for): def log_response(self, status_code, client_ip, x_forwarded_for):
# 记录每次响应的日志
logging.info( logging.info(
"method=%s path=%s client_ip=%s x_forwarded_for=%s status=%d", "method=%s path=%s client_ip=%s x_forwarded_for=%s status=%d",
self.command, self.command,
@ -29,48 +28,55 @@ class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
) )
def do_GET(self): 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') x_forwarded_for = self.headers.get('X-Forwarded-For')
remote_addr = self.client_address[0] 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) 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: try:
ip_obj = ipaddress.ip_address(client_ip) ip_obj = ipaddress.ip_address(client_ip)
if isinstance(ip_obj, ipaddress.IPv6Address) and ip_obj.ipv4_mapped: if isinstance(ip_obj, ipaddress.IPv6Address) and ip_obj.ipv4_mapped:
client_ip = str(ip_obj.ipv4_mapped) client_ip = str(ip_obj.ipv4_mapped)
except ValueError: except ValueError:
# 如果解析失败(非标准格式),尝试手工处理以防某些代理返回带方括号或端口 # If parsing fails (non-standard format), attempt manual handling to cope with some proxies
# 移除 IPv6 方括号及端口(如 [::ffff:127.0.0.1]:8080 # Remove IPv6 brackets and port (e.g. [::ffff:127.0.0.1]:8080)
s = client_ip s = client_ip
if s.startswith('[') and ']' in s: if s.startswith('[') and ']' in s:
s = s.split(']', 1)[0].lstrip('[') s = s.split(']', 1)[0].lstrip('[')
if s.count(':') >= 2 and s.startswith('::ffff:'): if s.count(':') >= 2 and s.startswith('::ffff:'):
# 处理可能带端口的情况 # Handle possible port by taking the last segment
s = s.split(':')[-1] s = s.split(':')[-1]
client_ip = s client_ip = s
# 发送响应 # Send response
status_code = 200 status_code = 200
self.send_response(status_code) self.send_response(status_code)
self.send_header("Content-type", "text/plain") self.send_header("Content-type", "text/plain")
self.end_headers() self.end_headers()
self.wfile.write(client_ip.encode()) self.wfile.write(client_ip.encode())
# 在响应后记录日志 # Log after responding
try: try:
self.log_response(status_code, client_ip, x_forwarded_for) self.log_response(status_code, client_ip, x_forwarded_for)
except Exception: except Exception:
logging.exception("Failed to log response") 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__": if __name__ == "__main__":
PORT = 8080 args = parse_args()
# 对于 AF_INET6 使用四元组绑定所有 IPv6 地址 PORT = args.port
# For AF_INET6 bind to all IPv6 addresses using a 4-tuple
server_address = ("::", PORT, 0, 0) server_address = ("::", PORT, 0, 0)
with TCPServer6(server_address, MyHTTPRequestHandler) as httpd: 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: try:
httpd.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) httpd.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
except Exception: except Exception: