用 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 1
还有 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
还有 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
1423 2023-04-11 15:59:13 +08:00 1
为什么之前没有这种工具
因为从 stun 获取 IP 是 stun 套件的其中一个示例功能,少有人单独掏出来 show 的 举例如 https://github.com/pion/stun/tree/master/cmd/stun-client ./stun_client 1.1.1.1:10101 |
19
1423 2023-04-11 16:08:32 +08:00 2
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 1
@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
Ghonewyn 2023-04-13 16:25:51 +08:00 1
@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/
|