Skip to content

Commit

Permalink
feat: use custom extip server
Browse files Browse the repository at this point in the history
  • Loading branch information
hrbrmstr committed Mar 3, 2023
1 parent 3d29076 commit b1efcf5
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 17 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<a name="v0.2.0"></a>
## [v0.2.0] - 2023-03-03
### Features
- now has the option to use a custom [extip server](https://github.com/hrbrmstr/extip-svr)


<a name="v0.1.0"></a>
## [v0.1.0] - 2023-02-28
### Features
Expand Down
43 changes: 39 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

Small Golang package/cli that uses special DNS resolvers to return your external IP address.

Presently it uses Google, OpenDNS, and Akamai. If there is a conflict between the resolver answers a message will be delivered on stderr with the conflicting values.
By default it uses Google, OpenDNS, and Akamai. If there is a conflict between the resolver answers a message will be delivered on stderr with the conflicting values.

Alternatively, you can specify an [extip server](https://github.com/hrbrmstr/extip-svr) to use. See below for how to do that.

## References

Expand All @@ -21,7 +23,40 @@ just build # requires https://github.com/casey/just
go install -ldflags "-s -w" github.com/hrbrmstr/extip@latest
```

## TODO
## Options

```
Lookup external IP address via DNS.
Defaults to using Akamai, OpenDNS, and Google services.
You can specify an extip server via the following command line options.
NOTE: Both server and domain should be specified to override default behavior.
More info about running an extip server can be found at <https://github.com/hrbrmstr/extip-svr>.
extip 0.2.0
Usage: extip [--server EXTIP_SERVER] [--domain DOMAIN] [--record-type RECORD_TYPE] [--port PORT]
Options:
--server EXTIP_SERVER, -s EXTIP_SERVER
extip-svr IP/FQDN. e.g., ip.rudis.net [env: EXTIP_SERVER]
--domain DOMAIN, -d DOMAIN
Domain to use for IP Lookup. e.g., myip.is [env: EXTIP_DOMAIN]
--record-type RECORD_TYPE, -r RECORD_TYPE
DNS record type to lookup. One of TXT or A. [default: TXT, env: EXTIP_RECORD_TYPE]
--port PORT, -p PORT Port extip resolver is listening on. [default: 53, env: EXTIP_PORT]
--help, -h display this help and exit
```

## Usage

Default:

- [ ] Spruce up the CLI to allow folks to choose from the existing list vs use all of them
- [ ] Allow folks to specify an endpoint and record type so it can be used with the companion server <https://github.com/hrbrmstr/extip-svr>
```
extipsvr
```

Use an extip server:

```
extip -s ip.rudis.net -d ip.is
```
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ module github.com/hrbrmstr/extip
go 1.19

require (
github.com/alexflint/go-arg v1.4.3 // indirect
github.com/alexflint/go-scalar v1.1.0 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/uo=
github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA=
github.com/alexflint/go-scalar v1.1.0 h1:aaAouLLzI9TChcPXotr6gUhq+Scr8rl0P9P4PnltbhM=
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
9 changes: 3 additions & 6 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set shell := ["zsh", "-cu"]
go build -ldflags "-s -w" -o bin/extip

@run: build
./extip
./bin/extip

# Be a good citizen
@fmt:
Expand All @@ -25,12 +25,9 @@ set shell := ["zsh", "-cu"]
GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -o bin/extip-darwin-amd64 main.go && cd bin && gzip extip-darwin-amd64
GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w" -o bin/extip-darwin-arm64 main.go && cd bin && gzip extip-darwin-arm64

# release binaries
@release:
gh workflow run release-binaries.yml

# Check results against dig. Requires dig.
@test: build
[ "$(dig myip.opendns.com @resolver1.opendns.com +short)" = "$(./bin/extip)" ] && echo "Passed OpenDNS test"
[ "$(dig o-o.myaddr.1.google.com @ns1.google.com TXT +short | tr -d '"')" = "$(./bin/extip)" ] && echo "Passed Google test"
[ "$(dig +short TXT whoami.ds.akahelp.net @$(dig +short +answer NS akamai.com | head -1) | grep ns | sed -e 's/[^0-9\.\:]//g')" = "$(./bin/extip)" ] && echo "Passed Akamai test"
[ "$(dig +short TXT whoami.ds.akahelp.net @$(dig +short +answer NS akamai.com | head -1) | grep ns | sed -e 's/[^0-9\.\:]//g')" = "$(./bin/extip)" ] && echo "Passed Akamai test"
[ "$(dig +short TXT myip.is @ip.rudis.net | tr -d '"')" = "$(./bin/extip)" ] && echo "Passed custom extip server test"
71 changes: 64 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ import (
"net"
"os"
"regexp"
"strconv"
"strings"
"time"

"github.com/alexflint/go-arg"
)

const(
version = "0.2.0"
resolverTimeout = 10000
defaultPort = "53"
defaultPort = 53

googleResolver = "ns1.google.com"
openDNSResolver = "resolver1.opendns.com"
Expand Down Expand Up @@ -44,13 +48,13 @@ func TrimSuffix(s, suffix string) string {
}

// Setup a specific resovler to use for DNS lookups
func UseResolver(resolver string) *net.Resolver {
func UseResolver(resolver string, port int) *net.Resolver {

return &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{Timeout: time.Millisecond * time.Duration(resolverTimeout)}
return d.DialContext(ctx, network, resolver + ":" + defaultPort)
return d.DialContext(ctx, network, resolver + ":" + strconv.Itoa(port))
},
}

Expand Down Expand Up @@ -82,7 +86,7 @@ func AkamaiExtIP() ([]string, error) {
return []string{""}, err
}

r := UseResolver(akamaiResolver)
r := UseResolver(akamaiResolver, defaultPort)
txts, err := r.LookupTXT(context.Background(), akamaiHost)

if (err != nil) {
Expand All @@ -98,7 +102,7 @@ func AkamaiExtIP() ([]string, error) {
// Get our local, external IP via Google's hack
func GoogleExtIP() ([]string, error) {

r := UseResolver(googleResolver)
r := UseResolver(googleResolver, defaultPort)
txts, err := r.LookupTXT(context.Background(), googleHost)

if (err != nil) {
Expand All @@ -112,7 +116,7 @@ func GoogleExtIP() ([]string, error) {
// Get our local, external IP via OpenDNS's hack
func OpenDNSExtIP() ([]string, error) {

r := UseResolver(openDNSResolver)
r := UseResolver(openDNSResolver, defaultPort)
ips, err := r.LookupHost(context.Background(), openDNSHost)

if (err != nil) {
Expand All @@ -123,10 +127,63 @@ func OpenDNSExtIP() ([]string, error) {

}

// Get our local, external IP via custom extip resolver
func CustomExtIP(resolver string, host string, rectype string, port int) ([]string, error) {

r := UseResolver(resolver, port)

var res [](string)
var err error

if (rectype == "A") {
res, err = r.LookupHost(context.Background(), host)
} else {
res, err = r.LookupTXT(context.Background(), host)
}

if (err != nil) {
res = []string{""}
}

return res, err

}

type args struct {
Server string `arg:"-s,--server,env:EXTIP_SERVER" help:"extip-svr IP/FQDN. e.g., ip.rudis.net" placeholder:"EXTIP_SERVER"`
Domain string `arg:"-d,--domain,env:EXTIP_DOMAIN" help:"Domain to use for IP Lookup. e.g., myip.is" placeholder:"DOMAIN"`
RecordType string `arg:"-r,--record-type,env:EXTIP_RECORD_TYPE" help:"DNS record type to lookup. One of TXT or A." placeholder:"RECORD_TYPE" default:"TXT"`
Port int `arg:"-p,--port,env:EXTIP_PORT" help:"Port extip resolver is listening on." placeholder:"PORT" default:"53"`
}

func (args) Description() string {
return "Lookup external IP address via DNS.\n\nDefaults to using Akamai, OpenDNS, and Google services.\nYou can specify an extip server via the following command line options.\nNOTE: Both server and domain should be specified to override default behavior.\nMore info about running an extip server can be found at <https://github.com/hrbrmstr/extip-svr>.\n"
}

func (args) Version() string {
return "extip " + version
}

// TODO: Make this a proper CLI with cmdline options since we have 3 services
func main() {

l := log.New(os.Stderr, "", 1)

var args args

arg.MustParse(&args)

if args.Server != "" && args.Domain != "" {
custom, cerr := CustomExtIP(args.Server, args.Domain, args.RecordType, args.Port)
if (cerr != nil) {
l.Println("No DNS resolutions worked.")
os.Exit(3)
} else {
fmt.Println(custom[0])
os.Exit(0)
}

}

opendns, oerr := OpenDNSExtIP()
google, gerr := GoogleExtIP()
Expand Down

0 comments on commit b1efcf5

Please sign in to comment.