Skip to content

Add DNS server to host-agent to use native host resolver #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,40 @@ on:
env:
GO111MODULE: on
jobs:
artifacts-darwin:
name: Artifacts Darwin
runs-on: macos-11
timeout-minutes: 20
steps:
- uses: actions/setup-go@v2
with:
go-version: 1.17.x
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Make darwin artifacts
run: make artifacts-darwin
- name: "Upload artifacts"
uses: actions/upload-artifact@v2
with:
name: artifacts-darwin
path: _artifact/
release:
runs-on: ubuntu-20.04
needs: artifacts-darwin
timeout-minutes: 20
steps:
- uses: actions/download-artifact@v2
with:
name: artifacts-darwin
path: _artifact/
- uses: actions/setup-go@v2
with:
go-version: 1.17.x
- name: Install gcc-aarch64-linux-gnu
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- uses: actions/checkout@v2
- name: "Compile binaries"
run: make artifacts
Expand Down
27 changes: 22 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,34 @@ jobs:
EXAMPLE: ${{ matrix.example }}
run: ./hack/test-example.sh examples/$EXAMPLE

artifacts:
name: Artifacts
# the release pipeline uses Linux, so we Linux here as well
artifacts-darwin:
name: Artifacts Darwin
runs-on: macos-11
timeout-minutes: 20
steps:
- uses: actions/setup-go@v2
with:
go-version: 1.17.x
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Make darwin artifacts
run: make artifacts-darwin

artifacts-linux:
name: Artifacts Linux
runs-on: ubuntu-20.04
timeout-minutes: 20
steps:
- uses: actions/setup-go@v2
with:
go-version: 1.17.x
- name: Install gcc-aarch64-linux-gnu
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Make artifacts
run: make artifacts
- name: Make linux artifacts
run: make artifacts-linux
20 changes: 13 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ PACKAGE := github.com/lima-vm/lima
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
VERSION_TRIMMED := $(VERSION:v%=%)

GO_BUILD := CGO_ENABLED=0 $(GO) build -ldflags="-s -w -X $(PACKAGE)/pkg/version.Version=$(VERSION)"
GO_BUILD := $(GO) build -ldflags="-s -w -X $(PACKAGE)/pkg/version.Version=$(VERSION)"

.PHONY: all
all: binaries
Expand Down Expand Up @@ -39,16 +39,18 @@ _output/bin/nerdctl.lima:

.PHONY: _output/bin/limactl
_output/bin/limactl:
$(GO_BUILD) -o $@ ./cmd/limactl
# The hostagent must be compiled with CGO_ENABLED=1 so that net.LookupIP() in the DNS server
# calls the native resolver library and not the simplistic version in the Go library.
CGO_ENABLED=1 $(GO_BUILD) -o $@ ./cmd/limactl

.PHONY: _output/share/lima/lima-guestagent.Linux-x86_64
_output/share/lima/lima-guestagent.Linux-x86_64:
GOOS=linux GOARCH=amd64 $(GO_BUILD) -o $@ ./cmd/lima-guestagent
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO_BUILD) -o $@ ./cmd/lima-guestagent
chmod 644 $@

.PHONY: _output/share/lima/lima-guestagent.Linux-aarch64
_output/share/lima/lima-guestagent.Linux-aarch64:
GOOS=linux GOARCH=arm64 $(GO_BUILD) -o $@ ./cmd/lima-guestagent
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 $(GO_BUILD) -o $@ ./cmd/lima-guestagent
chmod 644 $@

.PHONY: install
Expand All @@ -71,14 +73,18 @@ uninstall:
clean:
rm -rf _output

.PHONY: artifacts
artifacts:
.PHONY: artifacts-darwin
artifacts-darwin:
mkdir -p _artifacts
GOOS=darwin GOARCH=amd64 make clean binaries
$(TAR) -C _output/ -czvf _artifacts/lima-$(VERSION_TRIMMED)-Darwin-x86_64.tar.gz ./
GOOS=darwin GOARCH=arm64 make clean binaries
$(TAR) -C _output -czvf _artifacts/lima-$(VERSION_TRIMMED)-Darwin-arm64.tar.gz ./

.PHONY: artifacts-linux
artifacts-linux:
mkdir -p _artifacts
GOOS=linux GOARCH=amd64 make clean binaries
$(TAR) -C _output/ -czvf _artifacts/lima-$(VERSION_TRIMMED)-Linux-x86_64.tar.gz ./
GOOS=linux GOARCH=arm64 make clean binaries
GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc make clean binaries
$(TAR) -C _output/ -czvf _artifacts/lima-$(VERSION_TRIMMED)-Linux-aarch64.tar.gz ./
4 changes: 3 additions & 1 deletion docs/internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,6 @@ The volume label is "cidata", as defined by [cloud-init NoCloud](https://cloudin
- `LIMA_CIDATA_MOUNTS_%d_MOUNTPOINT`: the N-th mount point of Lima mounts (N=0, 1, ...)
- `LIMA_CIDATA_CONTAINERD_USER`: set to "1" if rootless containerd to be set up
- `LIMA_CIDATA_CONTAINERD_SYSTEM`: set to "1" if system-wide containerd to be set up
- `LIMA_CIDATA_SLIRP_GATEWAY`: set to the IP address of the host on the SLIRP network. `192.168.5.2`.
- `LIMA_CIDATA_SLIRP_GATEWAY`: set to the IP address of the host on the SLIRP network. `192.168.5.2`.
- `LIMA_CIDATA_SLIRP_DNS`: set to the IP address of the DNS on the SLIRP network. `192.168.5.3`.
- `LIMA_CIDATA_UDP_DNS_LOCAL_PORT`: set to the udp port number of the hostagent dns server (or 0 when not enabled).
8 changes: 8 additions & 0 deletions docs/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ The loopback addresses of the host is `192.168.5.2` and is accessible from the g

The DNS.

If `useHostResolver` in `lima.yaml` is true, then the hostagent is going to run a DNS server over udp, using the same socket number as `ssh.localPort`. This server does a local lookup using the native host resolver, so will deal correctly with VPN configurations and split-DNS setups, as well a mDNS (for this the hostagent has to be compiled with `CGO_ENABLED=1`).

This udp port is then forwarded via iptables rules to `192.168.5.3:53`, overriding the DNS provided by QEMU via slirp.

During initial cloud-init bootstrap, `iptables` may not yet be installed. In that case the repo server is determined using the slirp DNS. After `iptables` has been installed, the forwarding rule is applied, switching over to the hostagent DNS.

If `useHostResoler` is false, then DNS servers can be configured manually in `lima.yaml` via the `dns` setting. If that list is empty, then Lima will either use the slirp DNS (on Linux), or the nameservers from the `en0` host interface (on macOS).

## `vde_vmnet` (192.168.105.0/24)

[`vde_vmnet`](https://github.com/lima-vm/vde_vmnet) is required for adding another guest IP that is accessible from
Expand Down
4 changes: 2 additions & 2 deletions examples/alpine.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
images:
- location: https://github.com/lima-vm/alpine-lima/releases/download/v0.1.4/alpine-lima-std-3.13.5-x86_64.iso
- location: https://github.com/lima-vm/alpine-lima/releases/download/v0.1.5/alpine-lima-std-3.13.5-x86_64.iso
arch: "x86_64"
digest: "sha512:ef627d902645744ab9f62cfe9f741f84c9d544b36da113aef9410489db8d2430b9c37581c5958b4d7fc64dfb5267f4147a376a747cca053c8c43c65fc68474e0"
digest: "sha512:7b5c6f3691b88293cf94091c1d74629ee3227a5f5548d24497309d00f91338800d315d4a907b6c45a10d1a6ceb2bb7dc5b8a72d9be2e251f6979886ae0bf1274"

mounts:
- location: "~"
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/lima-vm/sshocker v0.2.2
github.com/mattn/go-isatty v0.0.14
github.com/mattn/go-shellwords v1.0.12
github.com/miekg/dns v1.1.43
github.com/norouter/norouter v0.6.4
github.com/nxadm/tail v1.4.8
github.com/opencontainers/go-digest v1.0.0
Expand Down Expand Up @@ -46,6 +47,7 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect
golang.org/x/text v0.3.6 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mibk/dupl v1.0.0/go.mod h1:pCr4pNxxIbFGvtyCOi0c7LVjmV6duhKWV+ex5vh38ME=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
Expand Down
13 changes: 13 additions & 0 deletions pkg/cidata/cidata.TEMPLATE.d/boot/07-host-dns-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
set -eux

# Wait until iptables has been installed; 30-install-packages.sh will call this script again
if command -v iptables >/dev/null 2>&1; then
if [ -n "${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}" ] && [ "${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}" -ne 0 ]; then
# Only add the rule once
if ! iptables-save | grep "udp.*${LIMA_CIDATA_SLIRP_GATEWAY}:${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}"; then
iptables -t nat -A OUTPUT -d "${LIMA_CIDATA_SLIRP_DNS}" -p udp --dport 53 -j DNAT \
--to-destination "${LIMA_CIDATA_SLIRP_GATEWAY}:${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}"
fi
fi
fi
25 changes: 22 additions & 3 deletions pkg/cidata/cidata.TEMPLATE.d/boot/30-install-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ update_fuse_conf() {
fi
}

INSTALL_IPTABLES=0
if [ "${LIMA_CIDATA_CONTAINERD_SYSTEM}" = 1 ] || [ "${LIMA_CIDATA_CONTAINERD_USER}" = 1 ]; then
INSTALL_IPTABLES=1
fi
if [ "${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}" -ne 0 ]; then
INSTALL_IPTABLES=1
fi

# Install minimum dependencies
if command -v apt-get >/dev/null 2>&1; then
DEBIAN_FRONTEND=noninteractive
Expand All @@ -20,7 +28,7 @@ if command -v apt-get >/dev/null 2>&1; then
apt-get install -y sshfs
fi
fi
if [ "${LIMA_CIDATA_CONTAINERD_SYSTEM}" = 1 ] || [ "${LIMA_CIDATA_CONTAINERD_USER}" = 1 ]; then
if [ "${INSTALL_IPTABLES}" = 1 ]; then
if [ ! -e /usr/sbin/iptables ]; then
apt-get install -y iptables
fi
Expand All @@ -36,7 +44,7 @@ elif command -v dnf >/dev/null 2>&1; then
dnf install -y fuse-sshfs
fi
fi
if [ "${LIMA_CIDATA_CONTAINERD_SYSTEM}" = 1 ] || [ "${LIMA_CIDATA_CONTAINERD_USER}" = 1 ]; then
if [ "${INSTALL_IPTABLES}" = 1 ]; then
if [ ! -e /usr/sbin/iptables ]; then
dnf install -y iptables
fi
Expand All @@ -63,7 +71,7 @@ elif command -v zypper >/dev/null 2>&1; then
zypper install -y sshfs
fi
fi
if [ "${LIMA_CIDATA_CONTAINERD_SYSTEM}" = 1 ] || [ "${LIMA_CIDATA_CONTAINERD_USER}" = 1 ]; then
if [ "${INSTALL_IPTABLES}" = 1 ]; then
if [ ! -e /usr/sbin/iptables ]; then
zypper install -y iptables
fi
Expand All @@ -80,6 +88,17 @@ elif command -v apk >/dev/null 2>&1; then
apk add sshfs
fi
fi
if [ "${INSTALL_IPTABLES}" = 1 ]; then
if ! command -v iptables >/dev/null 2>&1; then
apk update
apk add iptables
fi
fi
fi

if [ -n "${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}" ] && [ "${LIMA_CIDATA_UDP_DNS_LOCAL_PORT}" -ne 0 ]; then
# Try to setup iptables rule again, in case we just installed iptables
"${LIMA_CIDATA_MNT}/boot/07-host-dns-setup.sh"
fi

# update_fuse_conf has to be called after installing all the packages,
Expand Down
4 changes: 3 additions & 1 deletion pkg/cidata/cidata.TEMPLATE.d/lima.env
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ LIMA_CIDATA_CONTAINERD_SYSTEM=1
{{- else}}
LIMA_CIDATA_CONTAINERD_SYSTEM=
{{- end}}
LIMA_CIDATA_SLIRP_GATEWAY={{ .SlirpGateway }}
LIMA_CIDATA_SLIRP_DNS={{.SlirpDNS}}
LIMA_CIDATA_SLIRP_GATEWAY={{.SlirpGateway}}
LIMA_CIDATA_UDP_DNS_LOCAL_PORT={{.UDPDNSLocalPort}}
1 change: 0 additions & 1 deletion pkg/cidata/cidata.TEMPLATE.d/user-data
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@ resolv_conf:
{{- range $ns := $.DNSAddresses }}
- {{$ns}}
{{- end }}
- {{.SlirpDNS}}
{{- end }}
19 changes: 11 additions & 8 deletions pkg/cidata/cidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error {
return err
}
args := TemplateArgs{
Name: name,
User: u.Username,
UID: uid,
Containerd: Containerd{System: *y.Containerd.System, User: *y.Containerd.User},
SlirpNICName: qemu.SlirpNICName,
SlirpGateway: qemu.SlirpGateway,
SlirpDNS: qemu.SlirpDNS,
Name: name,
User: u.Username,
UID: uid,
Containerd: Containerd{System: *y.Containerd.System, User: *y.Containerd.User},
SlirpNICName: qemu.SlirpNICName,
SlirpGateway: qemu.SlirpGateway,
SlirpDNS: qemu.SlirpDNS,
}

// change instance id on every boot so network config will be processed again
Expand Down Expand Up @@ -131,7 +131,10 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error {
if err != nil {
return err
}
if len(y.DNS) > 0 {
if *y.UseHostResolver {
args.UDPDNSLocalPort = y.SSH.LocalPort
args.DNSAddresses = append(args.DNSAddresses, qemu.SlirpDNS)
} else if len(y.DNS) > 0 {
for _, addr := range y.DNS {
args.DNSAddresses = append(args.DNSAddresses, addr.String())
}
Expand Down
27 changes: 14 additions & 13 deletions pkg/cidata/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,20 @@ type Network struct {
Interface string
}
type TemplateArgs struct {
Name string // instance name
IID string // instance id
User string // user name
UID int
SSHPubKeys []string
Mounts []string // abs path, accessible by the User
Containerd Containerd
Networks []Network
SlirpNICName string
SlirpGateway string
SlirpDNS string
Env map[string]string
DNSAddresses []string
Name string // instance name
IID string // instance id
User string // user name
UID int
SSHPubKeys []string
Mounts []string // abs path, accessible by the User
Containerd Containerd
Networks []Network
SlirpNICName string
SlirpGateway string
SlirpDNS string
UDPDNSLocalPort int
Env map[string]string
DNSAddresses []string
}

func ValidateTemplateArgs(args TemplateArgs) error {
Expand Down
Loading