Updated on 2021-03-12
Setting up Docker on an IPv6 only VPS - e.g. at Mythic Beasts.
In this instance I have a /64 block allocated out of an (apparant) /48 subnet. The host needs to get its (link-local) gateway from RAs, but global IPs are hard-coded. EUI-64 is not used here.
Alpine as a host
Pros: Lightweight, so smaller attack surface
Cons: Busybox limitations, glibc alternative limitations. documentation ain’t great.
https://wiki.alpinelinux.org/wiki/Configure_Networking
/etc/network/interfaces
1
2
3
4
5
6
7
8
9
10
11
12
|
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
up ip link set $IFACE up
down ip link set $IFACE down
iface eth0 inet6 static
address 2a00:1098:88:xx:0:0:0:1
netmask 48
pre-up echo 1 > /proc/sys/net/ipv6/conf/eth0/accept_ra
|
Additional addresses
1
2
3
4
5
6
|
iface eth0 inet6 static
address 2a00:1098:88:xx:0:0:0:22
netmask 48
iface eth0 inet6 static
address 2a00:1098:88:xx:0:0:0:70
netmask 48
|
/etc/resolv.conf
Mythic Beasts NAT64 servers
1
2
3
|
search zabaglione.net
nameserver 2a00:1098:0:82:1000:3b:0:1
nameserver 2a00:1098:0:80:1000:3b:0:1
|
/etc/ssh/sshd_config
- Only v6, and only on primary IP
- No password login
- root ssh allowed, cert only
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
--- sshd_config.orig
+++ sshd_config
@@ -15,6 +15,9 @@
#ListenAddress 0.0.0.0
#ListenAddress ::
+AddressFamily inet6
+ListenAddress 2a00:1098:88:xx::1
+
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
@@ -29,7 +32,7 @@
# Authentication:
#LoginGraceTime 2m
-#PermitRootLogin prohibit-password
+PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
@@ -54,11 +57,11 @@
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
-#PasswordAuthentication yes
+PasswordAuthentication no
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
-#ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
|
https://wiki.alpinelinux.org/wiki/Docker#Installation
As root
Add Community Repo
1
2
3
4
5
6
7
|
zabaglione:~# cat /etc/apk/repositories
#/media/cdrom/apks
http://mirror.leaseweb.com/alpine/v3.11/main
http://mirror.leaseweb.com/alpine/v3.11/community
#http://mirror.leaseweb.com/alpine/edge/main
#http://mirror.leaseweb.com/alpine/edge/community
#http://mirror.leaseweb.com/alpine/edge/testing
|
Install Docker
1
|
zabaglione:~# apk add docker
|
Enable and start Docker
1
2
3
4
5
6
7
8
|
zabaglione:~# rc-update add docker boot
* service docker added to runlevel boot
zabaglione:~# service docker start
* Caching service dependencies ... [ ok ]
* Mounting cgroup filesystem ... [ ok ]
* /var/log/docker.log: creating file
* /var/log/docker.log: correcting owner
* Starting docker ... [ ok ]
|
And install docker-compose.
1
|
zabaglione:~# apk add docker-compose
|
See also https://docs.docker.com/engine/security/userns-remap/
However, this does have implications including stopping host networks from working.
1
2
3
4
|
zabaglione:~# adduser -SDHs /sbin/nologin dockremap
zabaglione:~# addgroup -S dockremap
zabaglione:~# echo dockremap:$(cat /etc/passwd|grep dockremap|cut -d: -f3):65536 >> /etc/subuid
zabaglione:~# echo dockremap:$(cat /etc/passwd|grep dockremap|cut -d: -f4):65536 >> /etc/subgid
|
/etc/docker/daemon.json
1
2
3
|
{
"userns-remap": "dockremap"
}
|
/etc/update-extlinux.conf
1
|
default_kernel_opts="... cgroup_enable=memory swapaccount=1"
|
than update the config and reboot
To allow IPv6 connectivity outbound from docker containers, can enable IPv6 global addresses for them -
https://collabnix.com/enabling-ipv6-functionality-for-docker-and-docker-compose/
These can apparently be > /64, e.g. /80 (though preferably no smaller)
Having done that, they need to be announced to the upstream router over NDP. This can be facilitated with ndppd.
This is not available in the Alpine packages, but is available as a docker image -
https://github.com/janeczku/ndppd-alpine
but
1
2
3
|
zabaglione:~# docker run -d --restart=unless-stopped -e IPV6_SUBNET="2a00:1098:88:xx:0:0:0:1" --cap-drop=ALL --cap-add=NET_ADMIN --cap-add=NET_RAW --net=host janeczku/ndppd-alpine
docker: Error response from daemon: cannot share the host's network namespace when user namespaces are enabled.
See 'docker run --help'.
|
Removing the namespace stuff allows this to run. Need to work out dependencies - do the containers have to be up when ndppd starts?
It may be better to have ndppd running native on the host, but it doesn’t currently build against the glibc replacement in Alpine.
npd6
There’s also npd6, available for Alpine in the edge/testing repo.
Add to /etc/npd6.conf
1
2
|
prefix=2a00:1098:0088:00xx:0001::/80
interface = eth0
|
And enable & start the service.
This seems to work nicely.
Docker Compose
Mapping services to IPv6 addresses can involve a lot of colons! To bind a port (here 22) to a v6 address (here 2a00:1098:88:xx::22), on the same port (22) we end up with configuration that looks like -
1
2
|
ports:
- 2a00:1098:88:xx::22:22:22
|
Interactive Environment
A test environment that I can ssh into in order to run network utilities etc.
1
2
3
4
5
6
7
8
|
build: ./toolkit
command: ["/usr/sbin/sshd", "-D"]
network_mode: bridge
ports:
- 2a00:1098:88:xx::22:22:22
volumes:
- /home:/home
restart: always
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
FROM alpine
MAINTAINER Matt Balyuzi (https://github.com/mbalyuzi)
RUN apk update && \
apk add --no-cache zsh mutt nmap iputils openssh rsync tmux apg keychain wget && \
rm -f /tmp/* /etc/apk/cache/*
RUN sed -i s/#PermitRootLogin.*/PermitRootLogin\ without-password/ /etc/ssh/sshd_config
RUN passwd -d root
COPY identity.pub /root/.ssh/authorized_keys
RUN sed -i -e "s/bin\/ash/bin\/zsh/" /etc/passwd
RUN addgroup matt && \
adduser -h /home/matt -s /bin/zsh -G matt -D matt && \
addgroup matt wheel
RUN passwd -d matt
COPY ssh_hostkeys/* /etc/ssh/
ENV SHELL /bin/zsh
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
|
Odds and ends
https://github.com/moby/moby/issues/36954
Interesting - https://zerotier.atlassian.net/wiki/spaces/SD/pages/7274520/Using+NDP+Emulated+6PLANE+Addressing+With+Docker - use ZeroTier as a v6 docker backplane.