在Python中获取IP地址

523 阅读4分钟

在这篇文章中,我们开发了一个Python脚本来获取私人、公共IP地址以及其他细节。

目录

  1. 什么是IP地址
  2. 私人与公共IP地址
  3. 域名系统(DNS)
  4. 使用案例
  5. 亲身体验。玩转IP地址

什么是IP地址

网络上的每一个节点(计算机)都被分配了一个唯一的号码,以识别它在网络上的身份。这个唯一的号码被编码在网络上为该节点发送的每个数据包中。

私人地址与公共地址

当你建立你的家庭网络时,分配给你的网络设备的地址将是私有的,除非你把它们公开。除非你在你的网关(面向互联网的路由器)上配置端口转发,否则公共地址是无法访问的。简而言之,私有地址是不能路由的。

而当你连接到ISP(互联网服务提供商)的网络时,你就获得了一个公共地址。与私人地址不同,公共地址是可路由的。

域名系统

人们通常称它为互联网的电话簿,确实如此。当你确实需要给保存在电话簿中的朋友打电话时,你能记住的最接近的东西就是他们的名字,这样就不需要记住你朋友的号码了。

上述情况类似于DNS对互联网的作用,而不是记住一个IP地址(8.8.8.8--谷歌的IP地址),你所要记住的只是google.com。

使用案例

除了允许网络上的通信,IP地址还被创造性地用于访问控制、地理位置等应用。

实践 玩转IP地址

    #!/usr/bin/python

    import sys
    import socket
    import requests
    import json
    from argparse import ArgumentParser


    ipify_json_endpoint = "https://api.ipify.org?format=json"


    def get_my_public_ip():
        response = requests.get(ipify_json_endpoint)
        return json.loads(response.text)["ip"]

        def get_my_private_ip():
            return socket.gethostbyname(socket.gethostname())

    def resolve_fqdn(fqdn):
        """
        fqdn: Fully Qualified Domain Name of the server
        """
        return socket.gethostbyname(fqdn)


    def echo_ip_address(ip_address):
        print("The IP Address is: %s" %(ip_address))
    
    
    if __name__ == "__main__":
        args_parser = ArgumentParser()
        args_parser.add_argument("--server", action="store_true")
        args_parser.add_argument("--fqdn", help="FQDN of server")
        args_parser.add_argument("--public", action="store_true")
        args_parser.add_argument("--private", action="store_true")
        args = args_parser.parse_args()

        if args.server:
            if not args.fqdn:
                args_parser.error("The Fully Qualified Domain Name is required")
                sys.eixt(-1)
            ip_address = resolve_fqdn(args.fqdn)
            echo_ip_address(ip_address)
        elif args.private:
            ip_address = get_my_private_ip()
            echo_ip_address(ip_address)
        elif args.public:
            ip_address = get_my_public_ip()
            echo_ip_address(ip_address)
        else:
            args_parser.error("Missing an action: --server or --private or --public")

了解代码
该脚本有三个程序(函数):

  1. get_my_public_ip():
    调用ipify的JSON端点,然后将响应转换为一个python字典,其中只有ip键(字段)。而这个字段有向API发出请求的节点的公共地址,这个节点就是你的电脑。

  2. get_my_private_ip():
    返回分配给节点的私有地址。
    它使用了socket模块的两个函数:
    gethostname()。返回节点的主机名
    gethostbyname()。将主机名解析为一个IP地址。

  3. resolve_fqdn():
    获取服务器的IP地址是一个DNS解析,因此,你需要一个服务器的完全合格的域名。
    FQDN解析是由*socket.gethostbyname()*完成的,它需要一个主机名作为参数,但对于我们的例子,我们需要FQDN,因为服务器不属于我们的域或本地网络。

  4. echo_ip_address()。这是一个展示性的函数,只是为了避免在代码中到处出现打印语句来打印一个IP地址。

  5. *如果 __name__ == '__main__':*这将检查模块(这个脚本)是否作为主程序运行,而不是从另一个模块运行,即由另一个python模块(文件)导入

  6. 该脚本还使用了ArgumentParser模块,因为它做了两个相关的任务,即获取公共IP和解析服务器的IP。所以我使用了一些开关来操纵它的行为。
    我想做得更花哨一些,所以请随意将代码分成两个文件,甚至实现一个更好的方法。

使用方法。

  1. 获取公共IP Screenshot-from-2022-08-13-20-37-27-1

  2. 获取私有IP Screenshot-from-2022-08-13-20-40-34

  3. 获取服务器的IP地址 server_ip

注意: 一个完全合格的域名(FQDN)是包含一个主机名和由点(.)连接起来的域名。

不通过外部API获得公共IP
关于公共IP地址,第一种方法是你会发现的最常见的解决方案,尽管不是唯一的方法。另一个选择是使用UpnP标准与你的互联网网关设备(IGD)进行通信。UpnP标准允许本地网络上的设备相互发现。

    import upnpy

    upnp = upnpy.UPnP()

    internet_gateway_device = upnp.get_igd() #1

    service_id = "WANPPPConnection.1" #2 It can also be WANIPConnection depeding on the connection type. PPP Point to Point protocol 
    service = device[service_id] #3
        print(service.GetExternalIPAddress(["NewExternalIPAddress"])
        

要求

  1. upnpy软件包
pip install upnpy

了解代码

  • 第1行:通过发送广播信息在网络上找到互联网网关设备(IGD)(Under the hood)。
  • 第二行:网络设备可以提供广泛的服务,这些服务由一个ID来识别,特别是对于我们的情况,我们可以使用WANPPPConnection.1或WANIPConnection。对于一个设备提供的服务列表,你可以使用。
    <device>.get_services()
  • 第3行:将目标服务分配给服务变量。
  • 最后,脚本向该服务发出请求,以检索公共IP地址。

使用方法

Screenshot-from-2022-08-12-12-47-01
Suprised!!!!, 是的,你应该这样做。

上述输出意味着,我的网络没有IGD,但我确实有,只是它不理解UPnP协议。

并非所有的设备都符合UPnP协议,因此在我的网络上测试,我的网关不理解UPnP协议。

编码愉快。