python 以编程方式发现公共 IP
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/613471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Discovering public IP programmatically
提问by hasen
I'm behind a router, I need a simple command to discover my public ip (instead of googling what's my ip and clicking one the results)
我在路由器后面,我需要一个简单的命令来发现我的公共 ip(而不是在谷歌上搜索我的 ip 并单击一个结果)
Are there any standard protocols for this? I've heard about STUN but I don't know how can I use it?
是否有任何标准协议?我听说过 STUN 但我不知道如何使用它?
P.S. I'm planning on writing a short python script to do it
PS我打算写一个简短的python脚本来做到这一点
采纳答案by thejoshwolfe
EDIT: curlmyip.com is no longer available. (thanks maxywb)
编辑: curlmyip.com 不再可用。(感谢maxywb)
Original Post:
原帖:
As of writing this post, curlmyip.com works. From the command line:
在撰写本文时,curlmyip.com 有效。从命令行:
curl curlmyip.com
It's a third-party website, which may or may not be available a couple years down the road. But for the time being, it seems pretty simple and to the point.
这是一个第三方网站,可能会或可能不会在未来几年内可用。但就目前而言,这似乎非常简单且切中要害。
回答by Carlos A. Ibarra
This may be the easiest way. Parse the output of the following commands:
这可能是最简单的方法。解析以下命令的输出:
- run a traceroute to find a router that is less than 3 hops out from your machine.
- run ping with the option to record the source route and parse the output. The first IP address in the recorded route is your public one.
- 运行 traceroute 以查找距您的机器不到 3 跳的路由器。
- 使用选项运行 ping 以记录源路由并解析输出。记录路由中的第一个 IP 地址是您的公共 IP 地址。
For example, I am on a Windows machine, but the same idea should work from unix too.
例如,我在一台 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
The 68.85.228.121 is a Comcast (my provider) router. We can ping that:
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
Voila! The 66.176.38.51 is my public IP.
瞧! 66.176.38.51 是我的公网 IP。
回答by Tim Matthews
I have made a program that connects to http://automation.whatismyip.com/n09230945.aspit is is written in D an getting someone else to tell you what they see your ip as is probably the most reliable way:
我制作了一个连接到http://automation.whatismyip.com/n09230945.asp的程序, 它是用 D 编写的,让其他人告诉你他们看到你的 ip 是什么,因为这可能是最可靠的方式:
/*
Get my IP address
*/
import tango.net.http.HttpGet;
import tango.io.Stdout;
void main()
{
try
{
auto page = new HttpGet ("http://automation.whatismyip.com/n09230945.asp");
Stdout(cast(char[])page.read);
}
catch(Exception ex)
{
Stdout("An exception occurred");
}
}
Edit python code should be like:
编辑python代码应该是这样的:
from urllib import urlopen
print urlopen('http://automation.whatismyip.com/n09230945.asp').read()
回答by mcr
Targeting www.whatsmyip.org is rude. They plea not to do that on the page.
定位 www.whatsmyip.org 是粗鲁的。他们恳求不要在页面上这样做。
Only a system on the same level of NAT as your target will see the same IP. For instance, your application may be behind multiple layers of NAT (this happens more as you move away from the US, where the glut of IPs are).
只有与目标处于同一 NAT 级别的系统才会看到相同的 IP。例如,您的应用程序可能位于多层 NAT 之后(当您远离 IP 过剩的美国时,这种情况发生得更多)。
STUN is indeed the best method. In general, you should be planning to run a (STUN) server somewhere that you application can ask: do not hard code other people's servers. You have to code to send some specific messages as described in rfc5389.
STUN确实是最好的方法。通常,您应该计划在应用程序可以要求的某个地方运行(STUN)服务器:不要硬编码其他人的服务器。您必须编码以发送一些特定的消息,如 rfc5389 中所述。
I suggest a good read of, and related links. http://www.ietf.org/html.charters/behave-charter.html
我建议好好阅读和相关链接。 http://www.ietf.org/html.charters/behave-charter.html
You may prefer to look at IPv6, and Teredo to make sure that you always have IPv6 access. (Microsoft Vista makes this very easy, I'm told)
您可能更喜欢查看 IPv6 和 Teredo,以确保您始终可以访问 IPv6。(有人告诉我,Microsoft Vista 使这变得非常容易)
回答by David Ferenczy Rogo?an
I like the ipify.org:
我喜欢ipify.org:
- it's free to use (even programmatically and even heavy traffic)
- response contains only the IP address without any garbage (no need for parsing)
- you can also request response in JSON
- works for both IPv4 and IPv6
- it's hosted in cloud
- it's open source
- 它可以免费使用(甚至以编程方式甚至流量大)
- 响应只包含IP地址,没有任何垃圾(不需要解析)
- 您还可以在 JSON 中请求响应
- 适用于 IPv4 和 IPv6
- 它托管在云中
- 它是开源的
$ curl api.ipify.org
167.220.196.42
$ curl "api.ipify.org?format=json"
{"ip":"167.220.196.42"}
回答by ryeguy
Whenever I wanted to do this, I would just scrape whatismyip.org. When you go to the site, it gives you your plain text public IP. Plain and simple.
每当我想这样做时,我都会抓取whatismyip.org。当您访问该站点时,它会为您提供纯文本公共 IP。干净利落。
Just have your script access that site and read the IP.
只需让您的脚本访问该站点并读取 IP。
I don't know if you were implying this in your post or not, but it isn't possible to get your public IP from your own computer. It has to come from an external source.
我不知道您是否在您的帖子中暗示了这一点,但是不可能从您自己的计算机上获取您的公共 IP。它必须来自外部来源。
2013 edit: This site returns an image now instead of text, so it's useless for this purpose.
2013 年编辑:此站点现在返回图像而不是文本,因此对于此目的毫无用处。
回答by bortzmeyer
As mentioned by several people, STUNis indeed the proper solution.
正如一些人提到的,STUN确实是正确的解决方案。
- a list of public STUN servers
- a free software STUN client
- The STUN standard
- 公共 STUN 服务器列表
- 一个免费软件STUN 客户端
- 该STUN标准
Here's a code example using pynat
Python module:
这是使用pynat
Python 模块的代码示例:
>>> import pynat
>>> pynat.get_ip_info()
('UDP Firewall', '192.0.2.2', 54320)
回答by jfs
To get your external ip, you could make a dns query to an opendns server with the special hostname "myip.opendns.com":
要获取您的外部 ip,您可以使用特殊主机名“myip.opendns.com”对 opendns 服务器进行 dns 查询:
from subprocess import check_output
ip = check_output(["dig", "+short", "@resolver1.opendns.com",
"myip.opendns.com"]).decode().strip()
On Windows, you could try nslookup
.
在 Windows 上,您可以尝试nslookup
.
There is no dns module in Python stdlib that would allow to specify custom dns server. You could use third party libraries e.g., Twistedto make the dns query:
Python stdlib 中没有允许指定自定义 dns 服务器的 dns 模块。您可以使用第三方库,例如Twisted进行 dns 查询:
from twisted.internet import task # $ pip install twisted
from twisted.names.client import Resolver
from twisted.python.util import println
def main(reactor):
opendns_resolvers = [("208.67.222.222", 53), ("208.67.220.220", 53)]
resolver = Resolver(servers=opendns_resolvers, reactor=reactor)
# use magical hostname to get our public ip
return resolver.getHostByName('myip.opendns.com').addCallback(println)
task.react(main)
Here's the same using dnspython
library:
import dns.resolver # $ pip install dnspython
resolver = dns.resolver.Resolver(configure=False)
resolver.nameservers = ["208.67.222.222", "208.67.220.220"]
print(resolver.query('myip.opendns.com')[0])
Here's asyncio
variant using aiodns
library:
这是asyncio
使用aiodns
library的变体:
$ pipenv install aiodns
$ pipenv run python -m asyncio
...
>>> import asyncio
>>> import aiodns # pip install aiodns
>>> resolver = aiodns.DNSResolver()
>>> resolver.nameservers = "208.67.222.222", "208.67.220.220"
>>> await resolver.query("myip.opendns.com", "A")
[<ares_query_a_result> host=192.0.2.2, ttl=0]
To get IPv6 address:
获取 IPv6 地址:
>>> resolver.nameservers = "2620:119:35::35", "2620:119:53::53"
>>> await resolver.query("myip.opendns.com", "AAAA")
回答by John Fricker
Your simplest way may be to ask some server on the outside of your network.
您最简单的方法可能是询问网络外部的某个服务器。
One thing to keep in mind is that different destinations may see a different address for you. The router may be multihomed. And really that's just where problems begin.
要记住的一件事是,不同的目的地可能会为您看到不同的地址。路由器可能是多宿主的。而这正是问题开始的地方。
回答by X-Istence
If the network has an UpNp server running on the gateway you are able to talk to the gateway and ask it for your outside IP address.
如果网络有一个在网关上运行的 UpNp 服务器,您可以与网关对话并询问它的外部 IP 地址。