Headscale - Real World Example

Page content

Tailscale on Public Intrnet

Setup

Let’s build a few machines around the world and get our hands dirty with headscale / tailscale.

headscale

  • amsterdam

tailscale

  • stockholm
  • miami
  • singapore
  • sydney

goal is to build a fullmesh network with all 4 tailscale clients

Headscale Server

Generate Install Key

let’s generate a reusable install key for all 4 clients. It’s valid for 1 hour.

headscale preauthkeys -n myfirstnamespace create --reusable -e 1h

-> e25a478b59514068a1b6c7104dde612b497ce36146a7f121

Tailscale Clients

on all 4 Clients, do the following:

  • install tailscale
  • start service
  • register on masternode
doas su -
pkg_add tailscale
rcctl enable tailscaled
rcctl restart tailscaled
tailscale up --login-server http://box-amsterdam.puffy.work:8080 --authkey e25a478b59514068a1b6c7104dde612b497ce36146a7f121

when all four clients are done, you can list them on the server

headscale node list
root@box-amsterdam # headscale node list
ID | Hostname      | Name                   | NodeKey | Namespace        | IP addresses                  | Ephemeral | Last seen           | Online | Expired
1  | box-miami     | box-miami-ijo574yw     | [/3uR4] | myfirstnamespace | 100.64.0.1, fd7a:115c:a1e0::1 | false     | 2022-09-22 19:56:24 | online | no
2  | box-stockholm | box-stockholm-wbmc6bx0 | [6ntlE] | myfirstnamespace | 100.64.0.2, fd7a:115c:a1e0::2 | false     | 2022-09-22 19:56:25 | online | no
3  | box-sydney    | box-sydney-6b7gdzz3    | [qKMWv] | myfirstnamespace | 100.64.0.3, fd7a:115c:a1e0::3 | false     | 2022-09-22 19:56:30 | online | no
4  | box-singapore | box-singapore-fw31ircq | [0cczy] | myfirstnamespace | 100.64.0.4, fd7a:115c:a1e0::4 | false     | 2022-09-22 19:56:47 | online | no

Routing Table from Singapore

root@box-singapore # route -n show -inet |grep tun0
100.64.0.1         100.64.0.4         UHS        0        0     -     8 tun0
100.64.0.2         100.64.0.4         UHS        0        0     -     8 tun0
100.64.0.3         100.64.0.4         UHS        0        0     -     8 tun0
100.64.0.4         100.64.0.4         UHl        0        0     -     1 tun0
100.64.0.4         100.64.0.4         UHS        0        0     -     8 tun0
100.100.100.100    100.64.0.4         UHS        0        0     -     8 tun0

Tailscale Status

root@box-singapore # tailscale status
fd7a:115c:a1e0::4 box-singapore-fw31ircq myfirstnamespace openbsd -
fd7a:115c:a1e0::1 box-miami-ijo574yw   myfirstnamespace openbsd active; direct [2001:19f0:9002:2c40:5400:4ff:fe25:ce75]:37025, tx 9704 rx 9628
fd7a:115c:a1e0::2 box-stockholm-wbmc6bx0 myfirstnamespace openbsd active; direct [2a05:f480:2000:1032:5400:4ff:fe25:ce78]:5492, tx 1884 rx 1628
fd7a:115c:a1e0::3 box-sydney-6b7gdzz3  myfirstnamespace openbsd active; direct [2401:c080:1800:47cf:5400:4ff:fe25:cfa3]:29140, tx 4172 rx 4072

Ping Check from Singapore

to miami

root@box-singapore # ping_loop 100.64.0.1
22:07:11 - 100.64.0.1 - ok - 241 ms
22:07:12 - 100.64.0.1 - ok - 241 ms

to stockholm

root@box-singapore # ping_loop 100.64.0.2
22:07:54 - 100.64.0.2 - ok - 283 ms
22:07:56 - 100.64.0.2 - ok - 281 ms

to sydney

root@box-singapore # ping_loop 100.64.0.3
22:08:10 - 100.64.0.3 - ok - 99.6 ms
22:08:11 - 100.64.0.3 - ok - 94.5 ms

to myself

root@box-singapore # ping_loop 100.64.0.4
22:08:35 - 100.64.0.4 - ok - 3.91 ms
22:08:36 - 100.64.0.4 - ok - 3.67 ms

Enable Routing

fine, we have full connectifity between the four nodes. but if we have some services a node and would like to announce it to others ? Let’s say we have 10.10.10.0/24 configured in singapore and we would like to announce it to our peers.

in singapore

tailscale up --advertise-routes=10.10.10.0/24 --login-server=http://box-amsterdam.puffy.work:8080

-> you get a message like this, but it seems working.

“Warning: Subnet routing and exit nodes only work with additional manual configuration on openbsd, and is not currently officially supported.”

check on headscale

root@box-amsterdam # headscale route list -i 4
Route         | Enabled
10.10.10.0/24 | false

the route get’s announced from singapore, but is not enabled/allowed on the headscale. we have to change this on the server.

enable the route

root@box-amsterdam # headscale route enable -a -i 4
Route         | Enabled
10.10.10.0/24 | true

the route is now allowed, but the other clients do not yet accept it.

check routes on clients

on sydney

root@box-sydney # route -n show -inet |grep tun0
100.64.0.1         100.64.0.3         UHS        0        0     -     8 tun0
100.64.0.2         100.64.0.3         UHS        0        0     -     8 tun0
100.64.0.3         100.64.0.3         UHl        0       99     -     1 tun0
100.64.0.3         100.64.0.3         UHS        0        0     -     8 tun0
100.64.0.4         100.64.0.3         UHS        0       32     -     8 tun0
100.100.100.100    100.64.0.3         UHS        0       35     -     8 tun0

accept routes on sydney

tailscale up --accept-routes --login-server=http://box-amsterdam.puffy.work:8080

check routing again

root@box-sydney # route -n show -inet |grep tun0
10.0.0/24          100.64.0.3         US         0        0     -     8 tun0
10.10.10/24        100.64.0.3         US         0        0     -     8 tun0
100.64.0.1         100.64.0.3         UHS        0        0     -     8 tun0
100.64.0.2         100.64.0.3         UHS        0        0     -     8 tun0
100.64.0.3         100.64.0.3         UHl        0       99     -     1 tun0
100.64.0.3         100.64.0.3         UHS        0        0     -     8 tun0
100.64.0.4         100.64.0.3         UHS        0       32     -     8 tun0
100.100.100.100    100.64.0.3         UHS        0       35     -     8 tun0

and you get the route !

-> 10.10.10/24 100.64.0.3 US 0 0 - 8 tun0

ping new subnet

on sydney, ping subnet in singapore

ping 10.10.10.1

tcpdump in singapore

root@box-singapore # tcpdump -i tun0 icmp
tcpdump: listening on tun0, link-type LOOP
22:40:56.651007 100.64.0.3 > 10.10.10.1: icmp: echo request
22:40:57.650505 100.64.0.3 > 10.10.10.1: icmp: echo request
22:40:58.651100 100.64.0.3 > 10.10.10.1: icmp: echo request

we get requests through the tunnel, but no reply.

configure network as loopback

in singapore, we announce a network 10.10.10.0/24, but it is not configured. let’s add a loopback interface with that address

ifconfig lo1 10.10.10.1/24

ping again

root@box-sydney # ping 10.10.10.1
PING 10.10.10.1 (10.10.10.1): 56 data bytes
64 bytes from 10.10.10.1: icmp_seq=116 ttl=255 time=93.880 ms
64 bytes from 10.10.10.1: icmp_seq=117 ttl=255 time=93.619 ms
64 bytes from 10.10.10.1: icmp_seq=118 ttl=255 time=93.466 ms

tcpdump again

root@box-singapore # tcpdump -i tun0 icmp
tcpdump: listening on tun0, link-type LOOP
22:44:45.813104 100.64.0.3 > 10.10.10.1: icmp: echo request
22:44:45.813218 10.10.10.1 > 100.64.0.3: icmp: echo reply
22:44:46.812834 100.64.0.3 > 10.10.10.1: icmp: echo request
22:44:46.812874 10.10.10.1 > 100.64.0.3: icmp: echo reply
22:44:47.813184 100.64.0.3 > 10.10.10.1: icmp: echo request
22:44:47.813230 10.10.10.1 > 100.64.0.3: icmp: echo reply

finally done :)

IPv6

few words about IPv6. Tunnels are build based on IPv6, the Overlay Network is Dualstacked. So, far, so good. What didn’t work for me, that was to register a IPv6 only Client. Headscale seems not to allow to Listen on IPv6 for Registration, so, at least during Registeration, Dualstack is needed.

https://tailscale.com/kb/1121/ipv6/

sha256: 8553c2e6ce946f5ee5d9b15eba8d99aea406c8e5f97711076e935229983f6164