以编程方式发现公共IP

时间:2009-03-05 03:18:43

标签: python ip-address tcp

我在路由器后面,我需要一个简单的命令来发现我的公共IP(而不是谷歌搜索我的IP并点击一个结果)

这有什么标准协议吗?我听说过STUN,但我不知道如何使用它?

P.S。我打算写一个简短的python脚本来做它

16 个答案:

答案 0 :(得分:23)

这可能是最简单的方法。解析以下命令的输出:

  1. 运行traceroute以查找距离您的计算机少于3跳的路由器。
  2. 使用选项运行ping以记录源路由并解析输出。记录路线中的第一个IP地址是您的公共IP地址。
  3. 例如,我在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 -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是我的公共IP。

答案 1 :(得分:17)

我制作了一个连接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");
      }
}

编辑python代码应该是:

from urllib import urlopen
print urlopen('http://automation.whatismyip.com/n09230945.asp').read()

答案 2 :(得分:11)

瞄准www.whatsmyip.org很粗鲁。他们请求不要在页面上这样做。

只有与目标处于同一NAT级别的系统才会看到相同的IP。 例如,您的应用程序可能位于多层NAT后面(当您离开美国时会发生更多这种情况,因为美国的IP过剩)。

STUN确实是最好的方法。 通常,您应该计划在某个地方运行(STUN)服务器 应用程序可以问:不要硬编码其他人的服务器。你必须编码 发送一些特定的消息,如rfc5389中所述。

我建议阅读和相关链接。 http://www.ietf.org/html.charters/behave-charter.html

您可能更愿意查看IPv6和Teredo以确保始终拥有IPv6访问权限。 (微软Vista让这很容易,我被告知)

答案 3 :(得分:8)

每当我想要这样做时,我就会刮掉whatismyip.org。当您访问该网站时,它会为您提供纯文本公共IP。简单明了。

让您的脚本访问该网站并阅读IP。

我不知道您是否在帖子中暗示这一点,但是无法从您自己的计算机上获取您的公共IP。它必须来自外部来源。

2013编辑:此网站现在返回图片而不是文字,因此无法用于此目的。

答案 4 :(得分:7)

编辑:curlmyip.com不再可用。 (感谢maxywb)

原帖

撰写本文时,curlmyip.com有效。从命令行:

curl curlmyip.com

这是一个第三方网站,可能会在未来几年内推出或未推出。但就目前而言,这似乎很简单。

答案 5 :(得分:7)

我喜欢ipify.org

  • 它可以免费使用(甚至可以通过编程方式,甚至是繁重的流量)
  • 响应只包含没有任何垃圾的IP地址(不需要解析)
  • 您也可以在JSON中请求回复
  • 适用于IPv4和IPv6
  • 它托管在云端
  • 它是开源的
td

答案 6 :(得分:5)

正如一些人所提到的,STUN确实是正确的解决方案。

答案 7 :(得分:3)

最简单的方法可能是询问网络外部的某个服务器。

要记住的一件事是,不同的目的地可能会为您看到不同的地址。路由器可以是多宿主的。而这正是问题开始的地方。

答案 8 :(得分:3)

如果网络上有网络上运行的UpNp服务器,您就可以与网关通话并询问其外部IP地址。

答案 9 :(得分:3)

要获取外部IP,您可以使用特殊主机名“myip.opendns.com”对服务器服务器进行dns查询:

from subprocess import check_output

ip = check_output(["dig", "+short", "@resolver1.opendns.com",
                   "myip.opendns.com"]).decode().strip()

在Windows上,您可以尝试nslookup

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)

使用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])

答案 10 :(得分:1)

另一种厚颜无耻的方式: 如果您的路由器可以选择在DynDNS更新它的网络IP,您可以使用以下内容获取自己的IP:

IP=`resolveip -s myalias.dyndns-home.com`

答案 11 :(得分:0)

Duck Duck Go可以根据自己的页面免费访问他们的API: https://duckduckgo.com/api

如果您需要IP地址,请输入以下网址: http://api.duckduckgo.com/?q=my+ip&format=json

返回一个JSON对象。 Answer属性有一个人类可读的字符串,其中包含您的IP地址。例如:

{
    ...
    "Answer": "Your IP address is ww.xx.yyy.zzz in <a href=\"http://open.mapquest.com/?q=aaaaa(bbbbb)\">aaaaa(bbbbb)</a>"
    ...
}

您可以使用split()[4]从该字符串中提取IP地址,如果您认为这个字符串不会改变或者您愿意定期修复它是安全的假设。

或者,如果您想要一个更加面向未来的方法,您可以循环split()返回的所有内容并返回第一个作为IP地址的项目。请参阅此处以验证IP地址: How to validate IP address in Python?

答案 12 :(得分:0)

curl api.infoip.io - 完整详情

curl api.infoip.io/ip - 只是ip地址

curl api.infoip.io/country - 只是国家/地区名称

......以及更多相同的

您可以在http://docs.ciokan.apiary.io/

查看文档

答案 13 :(得分:0)

我与您分享我检索服务器公共IP地址的方法,而无需使用外部API(当然这是一种安全风险)

INTERFACE=`ip route get 8.8.8.8 | grep 8.8.8.8 | cut -d' ' -f5`
HOSTIP=`ifconfig $INTERFACE | grep "inet " | awk -F'[: ]+' '{ print $4 }'`

如果您愿意,可以在python中使用:

import subprocess
public_ip = subprocess.check_output(["ifconfig `ip route get 8.8.8.8 | grep 8.8.8.8 | cut -d' ' -f5` | grep \'inet \' | awk -F'[: ]+' '{ print $4 }'"], shell=True)

它的工作原理如下:

  • 确定了访问Google dns服务器的最佳界面
  • 从该界面的ifconfig条目中获取公共IP

答案 14 :(得分:0)

以下是一些支持IPv4和IPv6的公共服务:

  • curl http://icanhazip.com
  • curl http://www.trackip.net/ip
  • curl https://ipapi.co/ip
  • curl http://api6.ipify.org
  • curl http://www.cloudflare.com/cdn-cgi/trace
  • curl http://checkip.dns.he.net

以下内容目前似乎仅支持IPv4:

  • curl http://bot.whatismyipaddress.com
  • curl http://checkip.dyndns.org
  • curl http://ifconfig.me
  • curl http://ip-api.com
  • curl http://api.infoip.io/ip

以编程方式进行HTTP调用很容易。因此,所有这些都应该相对易于使用,并且可以尝试多个不同的URL,以防万一失败。

答案 15 :(得分:-1)

现在,托管您自己的“无服务器” API相当便宜。所有主要的云提供商都为此提供服务。例如,使用Google Cloud Functions只需:

exports.requestIP = (req, res) => {
    res.status(200).send(req.ip)
}

这种方法可能比使用上面的公共服务更可靠,并且您可以在函数名称中添加一个长随机字符串以保持其私有性。