To get your external ip, you could make a dns query to an opendns server with the special hostname "myip.opendns.com":
from subprocess import check_output
ip = check_output(["dig", "+short", "@resolver1.opendns.com",
"myip.opendns.com"]).decode().strip()
On Windows, you could try 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., Twisted to make the dns query:
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:
$ 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:
>>> resolver.nameservers = "2620:119:35::35", "2620:119:53::53"
>>> await resolver.query("myip.opendns.com", "AAAA")