[dbohdan] 2015-03-18: Here is my solution for how to get your globally routable IP address. It is based on [http://serverfault.com/a/560059/204338%|%this helpful answer on ServerFault] and uses the [DNS] protocol. One upside of the approach is that the DNS servers used are more likely to last and have a good uptime than your average free your-IP-over-a-[REST]-API service. Download with [wiki-reaper]: `wiki-reaper -x 44451 0 > publicip-0.3.2.tm` ** See also ** * [how to find my own IP address] ** Code ** ====== #! /usr/bin/env tclsh # Public IP library for Tcl, version 0.3.2. # Copyright (c) 2015, 2016, 2020 D. Bohdan # License: MIT package require Tcl 8.5 namespace eval public-ip { package require dns variable ready 0 variable services { ipv4 { akamai { whoami.akamai.net -server ns1-1.akamaitech.net -type A } google { o-o.myaddr.l.google.com -server ns1.google.com -type TXT } opendns { myip.opendns.com -server resolver1.opendns.com -type A } } } } # Resolve the public IP address using one service. # Usage: query ?akamai|google|opendns? proc public-ip::query {{service google} {protocol ipv4}} { variable services set service [dict get $services $protocol $service] set id [dns::resolve \ {*}$service \ -command [namespace current]::query-ready \ ] vwait [namespace current]::ready if {[dns::status $id] ne {ok}} { set error [dns::error $id] dns::cleanup $id error $error } set rdata [dict get [lindex [dns::result $id] 0] rdata] dns::cleanup $id return $rdata } # Used internally by [query]. proc public-ip::query-ready token { set [namespace current]::ready 1 } # Resolve the public IP address using all of the available services for the # selected protocol. If one of the services returns a different address than # the others, generate an error. proc public-ip::query-all {{protocol ipv4}} { variable services set ip {} foreach service [dict keys [dict get $services $protocol]] { set resolved [query $service $protocol] if {$ip eq {}} { set ip $resolved set ipResolver $service } elseif {$ip ne $resolved} { error "got $protocol address $ip from $ipResolver but\ $resolved from $service" } } return $ip } proc public-ip::test {{protocol ipv4}} { puts [query-all $protocol] } # If this is the main script... if {[info exists argv0] && ([file tail [info script]] eq [file tail $argv0])} { public-ip::test } ====== <>Internet | Package