1. 项目概述一个极简主义的IP查询工具在开发和运维的日常工作中获取当前网络环境的公网IP地址是一个高频且基础的需求。无论是配置服务器安全组、调试网络策略、检查代理状态还是单纯想看看自己出口IP是什么我们都需要一个快速、准确、无干扰的工具。jason5ng32/MyIP这个项目正是为解决这个痛点而生。它不是一个功能繁杂的网络诊断平台而是一个极致专注、开箱即用的IP地址查询服务。简单来说MyIP就是一个部署在服务器上的Web应用。当你通过浏览器访问它时它会以最简洁的格式通常是纯文本或JSON返回你的客户端公网IP地址以及一些可选的网络信息如请求头、地理位置需额外配置等。它的核心价值在于“轻”和“专”。你不需要在复杂的网络工具页面里寻找IP信息也不需要忍受附带大量广告的免费查询网站。对于开发者、运维工程师甚至是普通的技术爱好者拥有一个自己掌控的、干净的IP查询端点能显著提升工作效率和体验。这个项目适合任何需要频繁获取IP信息的人。如果你是后端开发者可以在CI/CD脚本中调用它来验证部署服务器的出口IP如果你是运维可以用它来快速检查不同网络区域的连通性如果你在管理家庭网络或云服务器它也是一个方便的自我诊断工具。接下来我将从设计思路、部署实操、核心功能解析到高级定制完整拆解如何从零开始拥有你自己的“MyIP”服务。2. 核心设计思路与架构选型2.1 为什么选择自建而不是用公共API市面上免费的IP查询API很多例如ipify.org,icanhazip.com等它们简单好用。但自建MyIP服务有几个不可替代的优势完全可控与隐私你的IP查询请求不会经过第三方服务器避免了潜在的日志记录和数据关联风险。对于注重隐私和合规性的场景这一点至关重要。高可用性与稳定性公共API可能有访问频率限制、偶尔宕机或网络不可达。自建服务部署在自己的基础设施上稳定性和可用性由自己保障尤其在内网或特定VPC环境中自建服务是唯一选择。功能定制化你可以决定返回信息的格式和内容。比如除了IP你可能还想返回客户端User-Agent、请求协议HTTP/HTTPS、甚至根据IP解析出的自治系统号ASN用于网络分析。公共API通常不提供如此灵活的定制。学习与集成价值部署这样一个服务涉及Web服务器配置、容器化如Docker、反向代理、安全策略等实践是一个绝佳的、低风险的学习项目。你也可以轻松地将此端点集成到自己的监控系统或内部工具链中。jason5ng32/MyIP的实现通常非常轻量可能只是一个简单的Python Flask应用、Go语言编写的HTTP服务或者甚至是一个Nginx配置。其核心逻辑就是从HTTP请求中提取X-Forwarded-For或X-Real-IP等头如果经过代理或者直接获取远程连接地址REMOTE_ADDR然后将其返回。2.2 技术栈的权衡简单 vs. 功能一个基础的MyIP服务技术选型可以极其简单纯Nginx/APache配置通过配置返回纯文本。这是最轻量的方式零运行时依赖性能极高。但功能扩展性差难以添加复杂的逻辑如JSON格式化、地理查询。脚本语言Python/Node.js/PHP使用Flask、Express等微型框架几十行代码即可实现。优点是开发速度快易于扩展例如集成GeoIP数据库生态丰富。适合需要定制功能的场景。编译型语言Go/Rust编译成单个二进制文件部署简单性能卓越资源占用极低。特别适合对性能和分发便利性有要求的场景。jason5ng32/MyIP项目很可能采用了其中一种平衡性较好的方案。从命名习惯看开发者可能倾向于使用Go或Python。我们将以这两种语言为例展示从简到繁的不同实现层次。选择哪种取决于你的技术偏好和功能需求。对于绝大多数个人使用场景一个Python Flask应用加上Gunicorn作为WSGI服务器已经绰绰有余且最容易理解和修改。3. 从零开始部署你的MyIP服务我们将以最通用和易扩展的Python Flask Gunicorn Nginx方案为例演示完整的部署流程。这套组合成熟、稳定且便于后续添加任何你想要的逻辑。3.1 环境准备与项目初始化首先你需要一台具有公网IP的服务器云服务器VPS即可。系统以Ubuntu 22.04 LTS为例。步骤1系统更新与基础依赖安装# 更新软件包列表并升级现有包 sudo apt update sudo apt upgrade -y # 安装Python3, pip, 虚拟环境工具以及Nginx sudo apt install -y python3-pip python3-venv nginx步骤2创建项目目录与虚拟环境为项目创建一个独立的目录并在其中建立Python虚拟环境这是保持环境干净的最佳实践。# 创建项目目录你可以放在任何你喜欢的位置例如 /var/www sudo mkdir -p /var/www/myip sudo chown -R $USER:$USER /var/www/myip # 将所有权改为当前用户方便操作 cd /var/www/myip # 创建Python虚拟环境 python3 -m venv venv # 激活虚拟环境 source venv/bin/activate # 激活后命令行提示符前通常会出现 (venv) 字样步骤3编写核心的Flask应用代码在项目目录下创建主应用文件app.py。# app.py from flask import Flask, request, jsonify, make_response import os app Flask(__name__) def get_client_ip(): 安全地获取客户端真实IP地址。 优先检查常见的代理转发头最后回退到远程地址。 # 常见的代理服务器转发头按可信度从高到低检查 forwarded_headers [ X-Forwarded-For, X-Real-IP, CF-Connecting-IP, # Cloudflare True-Client-IP, # Akamai ] for header in forwarded_headers: ip request.headers.get(header) if ip: # X-Forwarded-For 可能包含逗号分隔的IP链取第一个 if header X-Forwarded-For and , in ip: ip ip.split(,)[0].strip() if ip: return ip # 如果没有代理头则使用连接远程地址 return request.remote_addr app.route(/) def index(): 默认根路径返回纯文本IP client_ip get_client_ip() # 返回纯文本并设置Content-Type response make_response(client_ip) response.headers[Content-Type] text/plain; charsetutf-8 return response app.route(/json) def json_api(): 返回JSON格式的详细信息 client_ip get_client_ip() data { ip: client_ip, user_agent: request.headers.get(User-Agent), protocol: request.scheme, # http 或 https method: request.method, host: request.headers.get(Host), } return jsonify(data) app.route(/health) def health(): 健康检查端点用于负载均衡或监控 return jsonify({status: healthy}), 200 if __name__ __main__: # 生产环境请不要使用此调试服务器 app.run(host0.0.0.0, port5000, debugFalse)步骤4安装Python依赖在激活的虚拟环境中创建requirements.txt文件并安装Flask。# 在 /var/www/myip 目录下 echo Flask2.3.3 requirements.txt pip install -r requirements.txt注意生产环境部署时app.run仅供测试。我们必须使用专业的WSGI服务器如Gunicorn。3.2 使用Gunicorn托管Flask应用Gunicorn是一个Python WSGI HTTP服务器性能远好于Flask自带的开发服务器。步骤1安装Gunicorn# 确保在虚拟环境中 pip install gunicorn20.1.0步骤2测试Gunicorn运行gunicorn --workers 2 --bind 0.0.0.0:8000 app:app--workers 2: 启动2个工作进程。通常建议设置为(2 * CPU核心数) 1。--bind 0.0.0.0:8000: 绑定到所有网络接口的8000端口。app:app: 第一个app是模块名即app.py第二个app是Flask应用实例名。此时访问http://你的服务器IP:8000应该能看到你的IP地址。访问http://你的服务器IP:8000/json会看到JSON数据。步骤3创建Systemd服务文件实现开机自启和进程管理这是将应用变为系统服务的关键一步。sudo nano /etc/systemd/system/myip.service将以下内容粘贴进去注意修改WorkingDirectory和User为你的实际路径和用户通常是非root用户如ubuntu。[Unit] DescriptionGunicorn instance to serve MyIP application Afternetwork.target [Service] Userubuntu # 替换为你的用户名 Groupwww-data WorkingDirectory/var/www/myip EnvironmentPATH/var/www/myip/venv/bin ExecStart/var/www/myip/venv/bin/gunicorn --workers 3 --bind unix:myip.sock -m 007 app:app [Install] WantedBymulti-user.targetunix:myip.sock: 让Gunicorn通过Unix套接字文件与Nginx通信这比TCP端口通信更高效、更安全。-m 007: 设置套接字文件的权限。步骤4启动并启用服务sudo systemctl daemon-reload # 重新加载systemd配置 sudo systemctl start myip # 启动服务 sudo systemctl enable myip # 设置开机自启 sudo systemctl status myip # 检查服务状态如果状态显示active (running)说明服务已成功启动。3.3 配置Nginx作为反向代理我们不直接对外暴露Gunicorn的端口而是用Nginx作为反向代理这样可以处理静态文件、SSL加密、负载均衡等。步骤1配置Nginx站点sudo nano /etc/nginx/sites-available/myip粘贴以下配置server { listen 80; listen [::]:80; server_name ip.yourdomain.com; # 替换为你的域名如果没有域名就用服务器IP location / { include proxy_params; proxy_pass http://unix:/var/www/myip/myip.sock; # 以下是一些重要的代理头设置确保能正确传递客户端信息 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 可选添加一些基础安全头 add_header X-Content-Type-Options nosniff; add_header X-Frame-Options DENY; add_header X-XSS-Protection 1; modeblock; }步骤2启用站点并测试Nginx配置sudo ln -s /etc/nginx/sites-available/myip /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置语法是否正确如果显示syntax is ok和test is successful则重启Nginx。sudo systemctl restart nginx现在通过浏览器访问你的服务器IP或配置的域名HTTP协议你应该能看到纯文本格式的你的公网IP了JSON接口则在/json路径下。3.4 启用HTTPS使用Let‘s Encrypt对于任何公网服务启用HTTPS都是必须的。我们将使用Certbot免费获取SSL证书。步骤1安装Certbotsudo apt install -y certbot python3-certbot-nginx步骤2获取并安装证书此步骤需要你的域名已正确解析到服务器IPsudo certbot --nginx -d ip.yourdomain.com按照交互提示操作输入邮箱、同意协议等。Certbot会自动修改你的Nginx配置将HTTP重定向到HTTPS并配置好SSL证书。步骤3设置证书自动续期Let‘s Encrypt证书有效期为90天Certbot会自动添加一个定时任务来续期但我们可以手动测试一下。sudo certbot renew --dry-run如果测试成功就说明自动续期配置正常。至此一个安全、高可用的自建MyIP服务就部署完成了。你可以通过https://ip.yourdomain.com访问它。4. 核心功能解析与高级定制基础服务搭建好后我们可以根据需求对它进行深度定制和功能增强。4.1 IP信息获取的逻辑深度剖析在app.py的get_client_ip()函数中我们实现了一个较为健壮的IP获取逻辑。这里有几个关键点需要理解代理链的处理当请求经过CDN如Cloudflare、负载均衡器或反向代理如Nginx时客户端的真实IP会被放在特定的HTTP头中。X-Forwarded-For是最常见的标准它记录了整个代理链的IP列表第一个IP通常是原始客户端IP。我们的代码取了第一个IP。信任边界这段代码隐式地信任了所有传入的X-Forwarded-For头。在内部网络或你完全掌控的代理环境下如你自己的Nginx这是安全的。但如果此服务直接暴露在公网恶意用户可以伪造这个头来欺骗服务。因此在安全要求极高的场景你必须配置你的前置代理如Nginx来清空或重置这些头或者只在可信的网络环境中使用此服务。IPv6支持Flask的request.remote_addr和我们的逻辑天然支持IPv6地址。如果你的服务器监听了IPv6并且客户端通过IPv6访问返回的将是IPv6地址。实操心得在实际生产环境中我强烈建议在Nginx配置中将客户端的真实IP设置到X-Real-IP头并在应用层只信任这个头。因为X-Real-IP通常由第一个可信的代理设置而X-Forwarded-For可能被沿途任何节点追加。你可以在Nginx的location块中添加proxy_set_header X-Real-IP $remote_addr;然后在Flask代码中优先读取X-Real-IP。4.2 集成GeoIP地理位置查询让服务返回IP所在的国家和城市会更有用。我们可以使用免费的GeoIP数据库如MaxMind的GeoLite2。步骤1下载并配置GeoIP2数据库首先在MaxMind官网注册账号免费生成一个许可证密钥。然后在服务器上安装更新工具和数据库。# 添加MaxMind的官方PPA sudo add-apt-repository ppa:maxmind/ppa sudo apt update sudo apt install -y geoipupdate libmaxminddb0 libmaxminddb-dev mmdb-bin # 配置geoipupdate编辑配置文件填入你的账号ID和许可证密钥 sudo nano /etc/GeoIP.conf在配置文件中找到AccountID和LicenseKey字段并填写。同时确保有EditionIDs GeoLite2-Country GeoLite2-City这一行。步骤2首次下载数据库并设置定时更新sudo geoipupdate这会将数据库文件下载到/usr/share/GeoIP/目录。你可以设置一个每周运行的cron job来自动更新。sudo crontab -e # 添加一行例如每周一凌晨3点更新 0 3 * * 1 /usr/bin/geoipupdate步骤3在Flask应用中集成GeoIP查询安装Python的geoip2库。pip install geoip2修改app.py增加地理信息查询功能。# 在文件开头导入 import geoip2.database # 在app创建后加载GeoIP数据库注意路径 GEOIP_CITY_DB_PATH /usr/share/GeoIP/GeoLite2-City.mmdb geoip_reader None try: geoip_reader geoip2.database.Reader(GEOIP_CITY_DB_PATH) print(fGeoIP database loaded successfully from {GEOIP_CITY_DB_PATH}) except FileNotFoundError: print(fWarning: GeoIP database not found at {GEOIP_CITY_DB_PATH}. Geo location disabled.) def get_geo_info(ip_address): 根据IP地址获取地理信息 if not geoip_reader: return None try: response geoip_reader.city(ip_address) return { country: response.country.name, country_code: response.country.iso_code, city: response.city.name, latitude: response.location.latitude, longitude: response.location.longitude, timezone: response.location.time_zone, } except (geoip2.errors.AddressNotFoundError, ValueError): # IP地址不在数据库中或格式错误 return None # 修改 /json 路由加入地理信息 app.route(/json) def json_api(): client_ip get_client_ip() data { ip: client_ip, user_agent: request.headers.get(User-Agent), protocol: request.scheme, method: request.method, host: request.headers.get(Host), } geo_info get_geo_info(client_ip) if geo_info: data[geo] geo_info return jsonify(data)重启Gunicorn服务后访问/json接口返回的JSON中就会包含geo字段里面有国家、城市、经纬度等信息。4.3 性能优化与安全加固一个看似简单的服务也需要考虑性能和安全性。性能优化Gunicorn工作进程根据服务器CPU核心数调整--workers数量。对于IO密集型的Web应用也可以使用异步工作器如gevent。pip install gevent # 在systemd服务文件中修改ExecStart ExecStart/.../gunicorn --worker-class gevent --workers 5 --bind unix:myip.sock -m 007 app:appNginx缓存对于根路径/的纯IP响应内容变化频率低对同一客户端可以考虑在Nginx层添加短期缓存。location / { proxy_cache myip_cache; proxy_cache_key $scheme$request_method$host$request_uri; proxy_cache_valid 200 10s; # 缓存200状态码响应10秒 add_header X-Cache-Status $upstream_cache_status; include proxy_params; proxy_pass http://unix:/var/www/myip/myip.sock; }同时需要在Nginx的http块中定义缓存区proxy_cache_path。安全加固限制请求速率防止恶意刷接口。可以在Nginx中配置限流。# 在http块中定义限流区 limit_req_zone $binary_remote_addr zoneip_limit:10m rate10r/s; server { ... location / { limit_req zoneip_limit burst20 nodelay; # ... 其他proxy配置 } }防火墙配置确保服务器防火墙如UFW只开放必要的端口80, 443, SSH。sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 22/tcp sudo ufw enable应用层日志记录访问日志便于审计和排查问题。确保Flask或Gunicorn的日志被正确配置和轮转。5. 常见问题与排查技巧实录即使部署步骤清晰在实际操作中仍可能遇到各种问题。以下是我在多次部署类似服务中积累的排查经验。5.1 服务无法访问502 Bad Gateway这是最常见的问题通常意味着Nginx无法连接到后端的Gunicorn套接字。排查步骤检查Gunicorn服务状态sudo systemctl status myip。查看是否运行正常是否有错误日志。检查套接字文件权限ls -la /var/www/myip/myip.sock。确保套接字文件存在且Nginx进程用户通常是www-data有读取权限。我们的systemd服务配置中-m 007使得文件权限为rwxrwx---所有者是启动Gunicorn的用户如ubuntu组是www-data。需要确保ubuntu用户在www-data组内或者调整权限。# 将用户ubuntu加入www-data组 sudo usermod -a -G www-data ubuntu # 需要重新登录生效或者修改套接字文件权限为更宽松的模式安全性降低 # sudo chmod 666 /var/www/myip/myip.sock # 不推荐仅临时测试检查Nginx错误日志sudo tail -f /var/log/nginx/error.log。在尝试访问服务时查看这里输出的具体错误信息通常非常直观。检查防火墙和SELinux确保没有防火墙规则阻止Nginx与套接字通信。如果使用SELinux可能需要调整策略。5.2 返回的IP地址是服务器IP或负载均衡器IP这说明反向代理的头信息没有正确传递。解决方案确认Nginx配置确保proxy_set_header指令包含了X-Real-IP和X-Forwarded-For。检查代理链如果你的服务器前面还有CDN如Cloudflare需要确保CDN配置了传递原始访客IP。对于Cloudflare你需要使用其提供的“连接”应用来获取真实IP或者信任CF-Connecting-IP头我们的代码已经包含了这个头。修改Flask代码的信任顺序如果确定第一层代理是可信的如你自己的Nginx可以在get_client_ip()函数中优先读取X-Real-IP并注释掉对其他头的检查以避免被伪造。5.3 GeoIP查询返回null或报错可能原因及解决数据库文件不存在或路径错误使用ls -la /usr/share/GeoIP/确认GeoLite2-City.mmdb文件是否存在。确保Flask代码中的路径完全一致。数据库文件权限问题确保运行Gunicorn的用户有读取该数据库文件的权限。sudo chmod 644 /usr/share/GeoIP/GeoLite2-City.mmdbIP地址格式问题或不在数据库中GeoIP数据库并非包含全球所有IP特别是某些新分配的IP段或内网IP。这是正常现象。可以在代码中增加更详细的异常捕获和日志记录以区分是文件错误还是IP未找到。内存不足加载大型MMDB文件需要内存。如果服务器内存非常小可能会失败。可以考虑使用国家级的数据库GeoLite2-Country.mmdb它更小。5.4 如何应对高并发访问虽然个人使用的MyIP服务并发量通常不高但如果你将其公开或集成到其他系统中可能需要考虑。升级硬件这是最直接的方式。确保服务器有足够的CPU和内存。优化Gunicorn配置增加--workers数量不超过2*CPU核心数1使用异步工作器gevent或eventlet。使用Nginx缓存如前所述对纯IP响应设置短时间缓存能极大减轻后端压力。考虑静态化对于根路径/的纯文本响应甚至可以将其完全静态化。例如用一个极简的脚本定期将本机IP写入一个静态文件Nginx直接服务这个文件。但这只适用于获取服务器自身IP的场景不适用于获取客户端IP。部署并维护一个自己的MyIP服务整个过程就像搭建了一个网络世界中的“镜子”。它简单但反射出的信息——你的公网IP——是连接数字世界的基石之一。从简单的文本响应到集成地理信息、添加健康检查、配置安全策略每一步的深化都让你对Web服务的部署、网络协议的理解更加透彻。这个项目最大的魅力在于它始于一个微小的需求却可以延伸出一个涵盖部署、配置、安全、优化的完整实践路径。当你下次需要IP时从容地打开自己搭建的那个页面那种掌控感和成就感是使用任何第三方服务都无法替代的。