diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..4f88109 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,67 @@ +name: Build + +on: [push, pull_request] + +jobs: + test: + strategy: + matrix: + go-version: [1.17.x] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Vet + run: go vet ./... + - name: Test + run: go test -v ./... + - name: Build + run: go build -v ./... + + build: + needs: test + strategy: + matrix: + include: + - arch: arm + arm: 5 + - arch: arm + arm: 6 + - arch: arm + arm: 7 + - arch: arm64 + - arch: amd64 + - arch: 386 + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Build + run: go build -v ./... + env: + GOOS: linux + GOARCH: ${{ matrix.arch }} + GOARM: ${{ matrix.arm }} + - uses: actions/upload-artifact@v1 + with: + name: avahi2dns-linux-${{ matrix.arch }}${{ matrix.arm }} + path: avahi2dns diff --git a/README.md b/README.md index e2420fe..db51cbb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,82 @@ -# avahi2dns +# avahi2dns [![Build](https://github.com/LouisBrunner/avahi2dns/actions/workflows/build.yml/badge.svg)](https://github.com/LouisBrunner/avahi2dns/actions/workflows/build.yml) + Small DNS server which interface with avahi (perfect for Alpine Linux and musl) + +## Building + +Requires go 1.16 or later + +``` +go build +``` + +## Usage + +```shell +$ ./avahi2dns -h +Usage: avahi2dns [--domains DOMAINS] [--addr ADDR] [--port PORT] [--debug] + +Options: + --domains DOMAINS, -d DOMAINS + comma-separated list of domains to resolve + --addr ADDR, -a ADDR address to bind on [default: localhost] + --port PORT, -p PORT port to bind on [default: 53] + --debug, -v also include debug information [default: false] + --help, -h display this help and exit +``` + +### Examples + +By default the server will bind to port 53 on localhost (not accessible outside the computer) and resolve any domain with the following extensions: `home`, `internal`, `intranet`, `lan`, `local`, `private`, `test` + +```shell +$ sudo ./avahi2dns +INFO[0000] starting DNS server addr="localhost:53" +... +``` + +Settings can be changed through command-line arguments or environment variables: + +```shell +$ ./avahi2dns -p 5454 -a '0.0.0.0' -d 'local,home' +or +$ BIND='0.0.0.0' PORT=5454 ./avahi2dns -d 'local,home' +``` + +You can also use the debug flag if you need more information about what the server is doing (probably overkill): + +```shell +$ ./avahi2dns -v -p 5454 +DEBU[0000]avahi2dns/server.go:14 main.runServer() connection to dbus... +DEBU[0000]avahi2dns/server.go:21 main.runServer() connection to avahi through dbus... +DEBU[0000]avahi2dns/server.go:37 main.runServer() adding dns handler domain=home +... +``` + +## Using with Alpine and Docker on Linux + +Linux DNS-resolution is done by the standard library (through functions like `getaddrinfo` or `gethostbyname`), unfortunately `musl` used by Alpine Linux doesn't support mdns out-of-the-box. +However you can easily add this lookup through `avahi2dns`: + +```shell +$ sudo ./avahi2dns & +INFO[0000] starting DNS server addr="localhost:53" +$ docker run --rm --entrypoint ash --net=host alpine -c 'apk add iputils && echo "nameserver 127.0.0.1" >> /etc/resolv.conf && ping your-name-host.local' +fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/armv7/APKINDEX.tar.gz +fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/armv7/APKINDEX.tar.gz +(1/2) Installing libcap (2.50-r0) +(2/2) Installing iputils (20210202-r0) +Executing busybox-1.33.1-r3.trigger +OK: 4 MiB in 16 packages +INFO[0006] forwarding query to avahi component=main name=your-name-host.local. protocol=0 type=A +INFO[0006] forwarding query to avahi component=main name=your-name-host.local. protocol=1 type=AAAA +PING your-name-host.local (172.16.16.2) 56(84) bytes of data. +64 bytes from 172.16.16.2 (172.16.16.2): icmp_seq=1 ttl=64 time=0.456 ms +64 bytes from 172.16.16.2 (172.16.16.2): icmp_seq=2 ttl=64 time=0.426 ms +64 bytes from 172.16.16.2 (172.16.16.2): icmp_seq=3 ttl=64 time=0.429 ms +64 bytes from 172.16.16.2 (172.16.16.2): icmp_seq=4 ttl=64 time=0.418 ms +``` + +Note: this requires your Docker container to use `--net=host` instead of the default `--net=bridge`, but that it might be possible without using the latest Docker distributions + +Note: `avahi2dns` is run as a background job for the sake of demonstration, you should really run it through `systemd` or similar diff --git a/query.go b/query.go index 8f047c8..83a1a17 100644 --- a/query.go +++ b/query.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "log" "github.com/holoplot/go-avahi" "github.com/miekg/dns" @@ -15,7 +14,7 @@ func createDNSReply(logger *logrus.Entry, aserver *avahi.Server, r *dns.Msg) *dn switch r.Opcode { case dns.OpcodeQuery: - for _, q := range m.Question { + for _, q := range r.Question { switch q.Qtype { case dns.TypeA: rr, err := avahiToRecord(logger, aserver, q.Name, avahi.ProtoInet, "A") @@ -55,7 +54,6 @@ func avahiToRecord(logger *logrus.Entry, aserver *avahi.Server, name string, pro if err != nil { return nil, fmt.Errorf("avahi resolve failure: %w", err) } - log.Println("ResolveHostName:", hn) rr, err := dns.NewRR(fmt.Sprintf("%s %s %s", name, recordType, hn.Address)) if err != nil { return nil, fmt.Errorf("failured to create record: %w", err)