我在路由器后面,我需要一个简单的命令来发现我的公共(public) ip(而不是在谷歌上搜索我的 ip 并单击一个结果)
是否有任何标准协议(protocol)?听说过 STUN 但不知道怎么用?
附:我打算写一个简短的python脚本来做它
最佳答案
这可能是最简单的方法。解析以下命令的输出:
- 运行 traceroute 以查找距离您的计算机不到 3 跳的路由器。
- 使用选项运行 ping 以记录源路由并解析输出。记录路由中的第一个 IP 地址是您的公共(public)地址。
例如,我在一台 Windows 机器上,但同样的想法也应该适用于 unix。
> tracert -d www.yahoo.com
Tracing route to www-real.wa1.b.yahoo.com [69.147.76.15]
over a maximum of 30 hops:
1 <1 ms <1 ms <1 ms 192.168.14.203
2 * * * Request timed out.
3 8 ms 8 ms 9 ms 68.85.228.121
4 8 ms 8 ms 9 ms 68.86.165.234
5 10 ms 9 ms 9 ms 68.86.165.237
6 11 ms 10 ms 10 ms 68.86.165.242
68.85.228.121 是 Comcast(我的提供商)路由器。我们可以ping通:
> ping -r 9 68.85.228.121 -n 1
Pinging 68.85.228.121 with 32 bytes of data:
Reply from 68.85.228.121: bytes=32 time=10ms TTL=253
Route: 66.176.38.51 ->
68.85.228.121 ->
68.85.228.121 ->
192.168.14.203
瞧! 66.176.38.51 是我的公共(public) IP。
执行此操作的 Python 代码(希望适用于 py2 或 py3):
#!/usr/bin/env python
def natIpAddr():
# Find next visible host out from us to the internet
hostList = []
resp, rc = execute("tracert -w 100 -h 3 -d 8.8.8.8") # Remove '-w 100 -h d' if this fails
for ln in resp.split('\n'):
if len(ln)>0 and ln[-1]=='\r': ln = ln[:-1] # Remove trailing CR
if len(ln)==0: continue
tok = ln.strip().split(' ')[-1].split('.') # Does last token look like a dotted IP address?
if len(tok)!=4: continue
hostList.append('.'.join(tok))
if len(hostList)>1: break # If we found a second host, bail
if len(hostList)<2:
print("!!tracert didn't work, try removing '-w 100 -h 3' options")
# Those options were to speed up tracert results
else:
resp, rc = execute("ping -r 9 "+hostList[1]+" -n 1")
ii = resp.find("Route: ")
if ii>0: return resp[ii+7:].split(' ')[0]
return none
def execute(cmd, showErr=True, returnStr=True):
import subprocess
if type(cmd)==str:
cmd = cmd.split(' ')
# Remove ' ' tokens caused by multiple spaces in str
cmd = [xx for xx in cmd if xx!='']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if type(out)==bytes: # Needed for python 3 (stupid python)
out = out.decode()
try:
err = err.decode()
except Exception as ex:
err = "!!--"+str(type(ex))+"--!!"
if showErr and len(err)>0:
out += err
if returnStr and str(type(out))=="<type 'unicode'>":
# Trying to make 'out' be an ASCII string whether in py2 or py3, sigh.
out = out.encode() # Convert UNICODE (u'xxx') to string
return out, proc.returncode
if __name__ == "__main__":
print("(This could take 30 sec)")
print(natIpAddr())
从命令行(在 Windows 上)或 python 程序中使用它:
import natIpAddr
myip = natIpAddr.natIpAddr()
print(myip)
关于python - 以编程方式发现公共(public) IP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/613471/