如何确定公网 IP 地址是一个让很多家用宽带用户经常遇到的问题。毕竟,固定 IP 地址的价格通常很高,不适用于家庭宽带。而我们的电信宽带运营商(ISP)通常会给我们分配动态 IP 地址。之所以称为动态 IP 地址,是因为每次拨号获得的 IP 地址可能会不同。有些运营商甚至会每天或不定期刷新 IP 地址池,在某个时间强制释放已经获得的 IP 地址并分配新的 IP 地址。
这对我们在家用宽带下运行的服务产生了影响——需要重新设置服务端 IP 地址,例如监控、网络存储等。这时,DDNS 就发挥了作用。现在大部分路由器都内置了 DDNS 客户端,例如花生壳等服务客户端。但这些客户端存在收费、不稳定和刷新间隔小等问题。对于拥有自己域名的朋友,可以使用 DNS 服务商的 API 自行实现 IP 更新操作,例如阿里云(Aliyun)和 Cloudflare 都可以实现。
本文不涉及如何使用 API 更新 DDNS 的内容,但调用 API 时有一个关键参数——公网 IP 地址。那么,如何获取当前运营商分配的公网 IP 地址呢?除了询问路由器(打开路由器管理界面查看 WAN 口信息)外,我们还可以通过一些网络服务进行检测。
1使用 Shell 命令获取公网 IP 地址
浏览器方式
如果我们使用浏览器打开这个地址checkip.amazonaws.com你就会发现你的公网IP地址赫然在目,互联网上的服务器总是能够知道是什么 IP地址的客户端发起了连接,当然就可以通过这种方式获取公网 IP,同样功能的网站有很多,这里列举部分我收集到的:
https://checkip.amazonaws.com
https://api.ipify.org
https://ifconfig.me/ip
https://icanhazip.com
https://ipinfo.io/ip
https://ipecho.net/plain
https://checkipv4.dedyn.io
cURL 方式
在命令行下我们当然不能为这点小事随便启动浏览器,我们可以请出另外一个功能强大的工具,那就是curl,cURL 是一个利用URL语法在命令行下工作的文件传输工具,关于cURL的快速用法可以参考阮一峰的网络日志《curl 的用法指南》,这里不再详述,最简单的用法就是curl 你要请求的网址
,比如curl checkip.amazonaws.com
。
使用 dig 命令
首次在别人脚本中看到这个方式获取公网IP觉得比较新奇,命令如下:
dig +short myip.opendns.com @resolver1.opendns.com
这个是由OpenDNS提供的服务,如果你的主机上没有安装dig命令,对于Debian系列系统可以通过apt-get install dnsutils
安装,这个命令的原理是指定resolver1.opendns.com
为域名myip.opendns.com
的解析服务器,为什么要指定,主要是避免 DNS 下游服务器缓存,另外这个指定的解析服务器被 OpenDNS 进行了特殊配置,其始终将域名myip.opendns.com
解析为发起 DNS 请求的客户端 IP 地址,这样也就实现了查找公网 IP的功能。
这个和 cURL 方式比有什么优势呢?当然是数据量更小传输更快,毕竟使用 cURL 发起 HTTP 请求必然会导致协议头等无关信息的交换,如果启用了 HTTPS/TLS 那么还要进行加密协商,效率会比较低,当然这种方式的缺点就是 DNS 查询容易被运营商审计和过滤,稳定性略差,不过我测试下来除了偶尔查询失败外其余情况是完全 OK 的。
2使用 Shell 脚本获取公网 IP 地址
至此我有个新的主意,那就是首先采用 dig 命令快速检索公网 IP 地址,如果失败则切换到 cURL 的方式,为了避免 cURL 单一服务器失败,采用轮询或者随机的方式,尽可能提高成功率。
使用 Bash Shell 脚本 do it,比如获取公网 IPv4 的脚本如下:
#!/bin/bash
# This script try to ensure gets the current IP address (as assigned by the ISP) from
# OpenDNS and other online services as fallbacks
hosts=("checkip.amazonaws.com" "api.ipify.org" "ifconfig.me/ip" "icanhazip.com" "ipinfo.io/ip" "ipecho.net/plain" "checkipv4.dedyn.io")
CURL=`which curl`
DIG=`which dig`
check=$($DIG +short myip.opendns.com @resolver1.opendns.com A)
if [ ! $? -eq 0 ] || [ -z "$check" ] || [[ ! $check =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Unable to get your public IP address by OpenDNS service, try to another way."
count=${#hosts[@]}
while [ -z "$check" ] && [[ $count -ne 0 ]]; do
selectedhost=${hosts[ $RANDOM % ${#hosts[@]} ]}
check=$($CURL -4s https://$selectedhost | grep '[^[:blank:]]') && {
if [ -n "$check" ] && [[ $check =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
break
else
check=""
count=$(expr $count - 1)
echo "The host $selectedhost returned an invalid IP address."
fi
} || {
check=""
count=$(expr $count - 1)
echo "The host $selectedhost did not respond."
}
done
fi
if [ -z "$check" ]; then
echo "Unable to get your public IP address. Please check your internet connection."
exit 1
fi
echo "Your public IP address is $check"
exit 0
上述脚本可以看出首先我使用 dig 方式查询 OpenDNS,如果查询失败或者返回为空或者不是 IP 地址,那么进入cURL模式,这里将可用服务器添加到 hosts 列表,并且随机抽取一个进行cURL,这里使用了curl -4s
参数-4s
分别表示仅使用 IPv4 方式连接(确保获取 IPv4 地址)和抑制进度条和错误信息,如果抽取的服务发生错误,那么进入循环再抽取一个,直到循环满最大 hosts 数停止。
3总结
大部分脚本甚至一些程序仅使用了一种方式获取公网 IP,但是互联网上这些服务往往是不可靠的,如果你所选用的服务出现故障,那么将会影响到你后续业务的开展,所以本文的核心思想还是多个备份,另外对于 cURL 方式采用随机确保所谓的“负载平衡”,避免 fallback 时过度请求某个服务导致 IP 被 Ban。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !