Skip to content

Commit

Permalink
Lookup public IP using HTTP
Browse files Browse the repository at this point in the history
Both OpenDNS and Google DNS has problems looking up the public IP on
IPv6 connections. Lookup up using HTTP (TCP) seems more stable. The
lookup time is about 110ms longer with this mechanism.

checkip.amazonaws.com for now only resolvs to IPv4 addresses. If that
would change we would need to lookup the A address of the domain and
connect to that IP manually. It's like 2 more lines of code only, if
connect_timeout isn't needed, then it's a bit more involved.
  • Loading branch information
carlhoerberg committed Jul 23, 2024
1 parent 43bfeec commit 60a8e0a
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions lib/sparoid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,16 @@ def write_cache
end
end

def public_ip
Resolv::DNS.open(nameserver: ["208.67.222.222", "208.67.220.220"]) do |dns|
dns.getresource("myip.opendns.com", Resolv::DNS::Resource::IN::A).address
def public_ip(host = "checkip.amazonaws.com")
Socket.tcp(host, 80, connect_timeout: 3) do |sock|
sock.sync = true
sock.print "GET / HTTP/1.1\r\nHost: #{host}\r\nConnection: close\r\n\r\n"
status = sock.readline(chomp: true)
raise ResolvError.new("#{host} response: #{status}") unless status.start_with? "HTTP/1.1 200 "
until sock.readline(chomp: true).empty?
# skip all headers
end
sock.readline(chomp: true) # this is the IP
end
end

Expand Down

0 comments on commit 60a8e0a

Please sign in to comment.