用 Rust 写了一个获取公网 IP 的小程序。
其实本来不想造这个轮子的,但是发现国内能稳定提供获取 IP 的服务少之又少,要么不稳定,要么会有各种限流。
今天突发奇想,NAT 打洞用的 STUN 服务本身就会返回客户端的 IP 地址,国内有不少大厂维护的 STUN 服务器,直接用肯定是最稳定的(因为大厂本身自己的服务也需要用到)。这些 STUN 服务器的稳定性应该不是个人搭建的 IP 查询服务能比的,跑路被打的风险也小很多。
简单 Google 了一下,竟然还没有人做过专门用来做这个的程序。我就基于 Rust 的 stun
Crate example 改了一个。
用起来非常简单,直接到 Release 页面下载自己架构的可执行文件 chmox +x uip
或者 cargo install uip
即可。编译的二进制大小也进行了优化,只有 1 MB 多点,也没有别的运行时依赖。
不带参数默认使用 Google 的 STUN 服务器,但是也可以使用国内的服务器,比如:
$ uip 203.0.113.1 $ uip stun.qq.com 203.0.113.1 $ uip stun.miwifi.com 203.0.113.1
通过返回值是否为 0
可以判断是否成功获得 IP 地址。
也欢迎大家分享可以使用的公开 STUN 服务器地址,可以在项目 README.md
里提 PR 。
更多能用的 STUN 服务器:
CF:
$ uip stun.cloudflare.com $ uip -4 stun.cloudflare.com # IPv4 only
国内 B 站的:
$ uip stun.chat.bilibili.com
![]() | 1 Aloento 2023-04-11 03:28:25 +08:00 via iPhone 这个好 |
2 Ricky123 2023-04-11 09:00:52 +08:00 支持+1, 作者要不要发布到 brew |
3 patrickyoung 2023-04-11 09:03:19 +08:00 via iPhone |
![]() | 4 molezznet 2023-04-11 09:03:52 +08:00 我把默认的改成 stun.syncthing.net 。 这样内外都能用了 否则出现 `Error: ErrTransactionTimeOut` |
![]() | 5 OutOfMemoryError 2023-04-11 09:06:16 +08:00 我用的 4.ipw.cn |
![]() | 8 asmoker 2023-04-11 09:21:35 +08:00 via Android curl ip.threep.top |
9 kenvix 2023-04-11 09:32:17 +08:00 可以做到 KB 级吗,路由器上 1MB 还是太紧张了 |
11 0o0O0o0O0o 2023-04-11 09:49:27 +08:00 ![]() 还有 telnet 方式和 DNS 方式: 例如 dig -t txt o-o.myaddr.l.google.com @ns1.google.com +short dig myip.opendns.com @resolver1.opendns.com +short dig whoami.akamai.net. @ns1-1.akamaitech.net. +short telnet telnetmyip.com 它们协议基础简单,也许真的能达到如 #9 所说的 KB 级?不过不清楚国内大厂有没有这类公益服务器。 |
15 cq65617875 2023-04-11 13:53:08 +08:00 |
17 yinmin 2023-04-11 15:40:29 +08:00 ![]() 还有 1 个地址能获取 IP 地址的: https://www.cloudflare.com/cdn-cgi/trace 给 1 段 python 函数,给需要做 ddns 的参考 ``` import re import requests import socket def find_my_ip(): url = 'https://www.cloudflare.com/cdn-cgi/trace' requests.packages.urllib3.util.connection.HAS_IPV6 = False match = re.search( r'ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', requests.get(url).text) if match: return match.group(1) else: return None print(find_my_ip()) ``` |
18 slowman ![]() 为什么之前没有这种工具 因为从 stun 获取 IP 是 stun 套件的其中一个示例功能,少有人单独掏出来 show 的 举例如 https://github.com/pion/stun/tree/master/cmd/stun-client ./stun_client 1.1.1.1:10101 |
19 slowman 2023-04-11 16:08:32 +08:00 ![]() telnet netgeartec.ga 8080 Connected to netgeartec.ga. Escape character is '^]'. HI HELLO 2.9 (2.9.2) 2021-11-30.2159.ffae0e0 GETIP YOURIP 1.1.1.1 speedtest.net 提供的 8080 端口上的服务器也都支持 GETIP 指令返回 IP |
![]() | 20 UnknoownUser 2023-04-11 17:17:08 +08:00 via iPhone |
![]() | 21 mikewang 2023-04-11 17:38:15 +08:00 via iPhone |
![]() | 22 bagel 2023-04-11 17:45:04 +08:00 名字好评,功能不好说,下个二进制专门干这个事感觉稍麻烦。 |
24 crazyweeds 2023-04-11 22:55:08 +08:00 |
![]() | 25 qsnow6 2023-04-11 23:50:30 +08:00 使用 myip.ipip.net 和 ip.sb 的人都没有长期使用这些服务,因为长期使用这些服务的人都知道它们不太可靠。我之前在家里运行了一个定时查询公网提交到 DDNS 的脚本,发现这两个服务经常会拒绝服务或者打不开。我猜测这可能是因为请求过多触发了风控。 我第一次听说这个 STUN 服务,非常感谢! 顺便也分享我使用的查询 IP 的接口, 非常稳定: http://checkip.amazonaws.com/ 。 |
![]() | 26 xiangyuecn 2023-04-11 23:52:23 +08:00 今天刚好在找免费 turn 服务,qq 的也挺好用,本地网卡 ip 、外网 ip 统统拿下 var cOnn=new RTCPeerConnection({iceServers:[{ urls:["stun:stun.qq.com"] }]}) conn.Onicecandidate=function(e){ if(e.candidate){ if(/([\d\.]+) \d+ typ (\w+)/.test(e.candidate.candidate)) console.log(RegExp.$2+" ip: "+RegExp.$1); }else{ console.log("完成"); } } conn.createDataChannel("test") var offer=await conn.createOffer() conn.setLocalDescription(offer) |
![]() | 27 xiangyuecn 2023-04-11 23:59:27 +08:00 STUN 在线测试 https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ 两个域名看起来比较老牌的服务,好像都是德国的: stun.sipgate.net stun.voipstunt.com |
![]() | 28 dndx OP ![]() @qsnow6 没错,我测试 ipip 也经常超时或者跳出来 5 秒盾,总体来说稳定性还是达不到要求。 国内能提供稳定 IP 查询接口的太少了。找来找去还是大厂的 STUN 服务器最稳定,比如 B 站的就是他们用来做直播 WebRTC P2P 的,甚至还写了优化文章: https://www.bilibili.com/read/cv19672394?from=articleDetail ,必然比各种公益性的服务要靠谱点。 |
![]() | 29 dndx OP @0o0O0o0O0o 公益的就难了,大厂 STUN 本来设计的就不是公益服务,所以可用性要靠谱点...国内的公益服务基本都不持久 |
![]() | 30 dndx OP @qsnow6 实际上 `stun.qq.com` 甚至还做了 GeoDNS 国内分区解析,算是很用心了。可用性不太需要担心,甚至可以顺带作为络通断的判断。 |
![]() | 32 someonedeng 2023-04-12 00:56:01 +08:00 ip.sb 已经刻进 dna |
33 crazyweeds 2023-04-12 01:11:16 +08:00 @Ricky123 确实发布一下比较方便,虽然我个人网站支持,但确实命令行来得快。 |
![]() | 34 serafin 2023-04-12 05:00:42 +08:00 我发个长亿点点的 curl -s https://www.cloudflare.com/cdn-cgi/trace | awk -F= '/^ip/{print $2}' curl -s https://1.1.1.1/cdn-cgi/trace | awk -F= '/^ip/{print $2}' curl -s visa.com/cdn-cgi/trace | awk -F= '/^ip/{print $2}' |
![]() | 35 tux 2023-04-12 06:59:42 +08:00 怎么没有 windows 版? |
![]() | 36 swulling 2023-04-12 08:20:22 +08:00 Python 的话直接用 aiostun 库就行了。 |
![]() | 37 v2wtf 2023-04-12 09:16:32 +08:00 提个意见:主要面向国内的程序,不要默认 G 家服务器。 这种东西最重要的事情之一是:方便。 如果默认 G 家服务器,那么每次还得手动输入个国内服务器地址,或者写个 shell 脚本包一道。 这么麻烦,我为何不直接 curl ip.sb? |
![]() | 38 v2wtf 2023-04-12 09:19:40 +08:00 除上面的意见之外,我觉得 OP 这个思路是对的。 不需要自己搭建服务器,有大厂稳定性,零依赖的东西用起来真的很爽。 |
![]() | 39 dndx OP @v2wtf 感谢建议。实际上 G 家的 STUN 服务器在国内用起来也没问题,所以这个默认值也不是完全没道理。UDP 3478 比 TCP 443 被阻塞的概率也低多了。 |
![]() | 40 v2wtf 2023-04-12 15:35:32 +08:00 ![]() @dndx 我下载回来第一次运行 uip 就是超时,看了下上面说的换了国内服务器才测试成功,所以才给出你提的建议。 第一次运行直接就失败,所以默认服务器成功率就不可能高。 |
![]() | 42 qsnow6 2023-04-12 20:11:54 +08:00 @dndx #41 ipv4 也有一定机率会连不通, 可能是 Google 的服务在墙内被干扰了. ```shell $ ./uip_x86_64-unknown-linux-musl -4 Error: ErrTransactionTimeOut ``` |
![]() | 43 dndx OP ![]() @qsnow6 我觉得你说的很有道理,在 ipip 上测了一下,好像 `stun.l.google.com` 在国内一些地方的确是解析不出来(主要是联通)。 刚发布了一个新版本 `v0.1.5`,在这个版本里默认的服务器已经改为了 `stun.cloudflare.com`,应该会好一些。考虑到国外的用户,不太想用国内的服务器作为默认值,希望理解。 |
45 kaddusabagei38 2023-04-13 10:52:12 +08:00 这个思路很棒 |
![]() | 46 devliu1 2023-04-13 11:12:00 +08:00 curl ip.3322.org |
![]() | 47 AokiHina 2023-04-13 16:25:51 +08:00 ![]() @tux https://github.com/amorphobia/uip 已经有大佬改出来了 windows 下的 target |
![]() | 48 dndx OP @Ghonewyn @tux Windows 版已经打出来了 https://github.com/dndx/uip/releases/tag/v0.1.6 感谢 amorphobia 贡献 https://github.com/dndx/uip/pull/1 我没有 Windows 系统,希望能有人帮忙测试一下能不能用。 |
49 dorothyREN 2023-04-16 13:03:49 +08:00 |
![]() | 50 mohumohu 2023-04-20 16:29:48 +08:00 OP 的项目不错,是否可以支持 SOCKS5 代理?因为 stun 用来测 socks 的 nat type 挺方便的,最好支持一次性重试多个列表。 另外公网获取 IP 的也有挺多 URL 可以用的,OP 可以看看这个 DDNS 脚本里面内置了一些获取 IP 的 URL: https://github.com/kkkgo/UE-DDNS |
51 fox233 2023-04-28 14:54:21 +08:00 releases 里面为啥没有 x86_64 的 Linux 文件呢?只有安卓的和 arm 的 |
![]() | 52 dndx OP |
53 EsWann 2023-07-07 03:10:18 +08:00 可以看下 https://www.ipip.sh/ |