Python IP地址发现代码给出外部IP而不是eth0设备IP

标签 python amazon-web-services

我有一个 python 类,它可以获取您所在的本地计算机的 IP 地址。它适用于实际硬件(除非是涉及桥接设备的 MacOS)或本地虚拟机。这是代码:

class IPAddress:
    ip_address = None

    def __init__(self):
        return

    def _get_interface_ip(self,ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s',
                            ifname[:15]))[20:24])

    # does not work on MacOS with bridged devices such as vboxnet0, tap0, tun0
    def get_lan_ip(self):
        hostname = socket.gethostname()
        ip = u''
        try:
            ip = socket.gethostbyname(hostname)
        except socket.gaierror, e:
            try:
                ip = socket.gethostbyname(u'localhost')
            except: pass

        if ip.startswith("127.") and os.name != "nt":
            interfaces = [
                "eth0",
                "eth1",
                "eth2",
                "en0",
                "en1",
                "en2",
                "wlan0",
                "wlan1",
                "wifi0",
                "ath0",
                "ath1",
                "ppp0",
                ]
            for ifname in interfaces:
                try:
                    ip = self._get_interface_ip(ifname)
                    break
                except IOError:
                    pass
        return ip

# Find out this instance
x = IPAddress()
server_ip = x.get_lan_ip()

除了 AWS 之外,这似乎在任何地方都适用。在 AWS 上,ifconfig eth0 提供分配给 eth0 的内部 IP 地址,而该类提供与访问实例关联的外部 CNAME IP 地址(在 EC2 Classic 中)。

什么给了?有没有更好的方法来进行 self 发现(例如)boto?

最佳答案

首先,我不会使用 gethostbyname() 或其同类。这样做依赖于您无法控制的外部数据库,而且这些数据库通常不是最新的。

接下来,我不会调用ioctl()。任何特定 ioctl 的存在,更不用说其行为,都没有跨操作系统标准化。

如果是我,我会connect()到一些外部服务,然后调用socket.getsockname():

def get_my_addr():
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  s.connect(('8.8.8.8', 53))
  return s.getsockname()[0]

如果这不起作用,我会 connect() 到基于 TCP 的服务:

def get_my_addr():
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect(('www.google.com', 80))
  return s.getsockname()[0]

关于Python IP地址发现代码给出外部IP而不是eth0设备IP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24896141/

相关文章:

python - 用pip安装文件和复制粘贴有什么区别

node.js - 如何使用 aws lambda(无服务器架构)开发类似套接字的方法

amazon-web-services - 为什么AWS KMS加密/解密不需要数据 key ?

python - Python是如何实现内置函数pow()的?

python - PyCharm 认为函数 "open"没有参数 "opener"

python - Pandas 嵌套的 groupby 给出了意想不到的结果

python - 如何在 django tastypie json 上附加 success=true

amazon-web-services - Terraform 是否提供与 S3 和 DynamoDB 的强一致性?

amazon-web-services - 我可以使用 cloud-init 来安装和配置 Chef,但不实际运行它吗?

mysql - 如果数据库子网组同时包含公共(public)/私有(private)子网,则 RDS 实例部署在哪个 AZ