summaryrefslogtreecommitdiff
path: root/src/tailscale.thrust
blob: 0019dd2db16f53b1955d90b43158f500a58ca2e1 (plain)
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
---
title: Tailscale
date: 2020-04-08
diagram source: |
	graph {
		rankdir="LR";

		subgraph cluster_0 {
			label = "Tailscale VPN";
			phone   [ label="phone"  ];
			relay   [ label="relay"  ];
			server  [ label="server" ];

			phone -- relay   [ style="dashed" ];
			phone -- server  [ style="dashed" ];
			relay -- server  [ style="dashed" ];
		}

		subgraph cluster_1 {
			label = "LAN";
			bulb      [ label="bulb"     ];
			internet  [ label="internet" ];
			router    [ label="router"   ];

			relay  -- bulb     [ style="dashed" ];
			relay  -- router   [ style="dashed" ];
			router -- internet;
		}
	}
---
{% extends 'templates/base.html' %}
{% block body %}
	<nav>
		<a href='/projects'>&gt; projects</a>
	</nav>

	<header>
		<h1>{{ title }}</h1>
	</header>

	<article>
	{% markdown %}
	[Tailscale](https://tailscale.com) is a Virtual Private Network (VPN) product for creating simple low-configuration VPNs between Linux, Mac, and Windows computers, as well as iOS devices.

	Rather than a "hub and spoke" model, where all devices dial in to the same VPN server, it builds a peer-to-peer network of [WireGuard](https://www.wireguard.com/) connections between your machines, with Tailscale itself authenticating and arranging those connections.

	I have been using its free tier for a few weeks, and below are some of my notes.

	<details markdown='1'>
	<summary>contents…</summary>
	<div markdown='block'>

	[TOC]

	</div>
	</details>

	## Bridging a LAN to the VPN

	One nice feature of Tailscale is the ability to bridge existing networks with the VPN.
	This is very useful for devices in the home that cannot run Tailscale themselves, such as IoT devices.

	Here I will show how I have bridged Tailscale with my LAN.
	This is an adaptation of the [guide from Tailscale themselves](https://tailscale.com/kb/1019/install-subnets).

	First, some definitions:

	- The **relay node** is the computer on my LAN doing the bridging.
	- The LAN-facing network interface on my relay node is **`enp2s0`**, but yours may differ.
	- The subnet for my LAN is **`192.168.16.0/24`**, but yours may differ.
	
	This example will be using [nftables](https://en.wikipedia.org/wiki/Nftables), but can also be done with [iptables](https://en.wikipedia.org/wiki/Iptables).

	### In abstract

	<svg xmlns='http://www.w3.org/2000/svg'
	     viewBox='0.00 0.00 404.65 254.00'
	     width='405pt' height='254pt'
	     style='font-family: "Times New Roman", Times, serif; font-size: 12pt; font-weight: lighter;'>
		<g transform='scale(1 1) rotate(0) translate(4 250)'>
			<polygon points='8,-144 8,-238 278.42,-238 278.42,-144 8,-144' />
			<text text-anchor='middle' x='143.21' y='-222.8'>Tailscale VPN</text>
			<polygon points='199.49,-8 199.49,-136 388.65,-136 388.65,-8 199.49,-8' />
			<text text-anchor='middle' x='294.07' y='-120.8'>LAN</text>
			<ellipse cx='47.72' cy='-180' rx='31.94' ry='18' />
			<text text-anchor='middle' x='47.72' y='-175.8'>phone</text>
			<ellipse cx='143.22' cy='-170' rx='27.56' ry='18' />
			<text text-anchor='middle' x='143.22' y='-165.8'>relay</text>
			<path stroke-dasharray='5,2' d='M79.08,-176.75C90.81,-175.5 104.11,-174.08 115.48,-172.86' />
			<ellipse cx='238.71' cy='-180' rx='31.92' ry='18' />
			<text text-anchor='middle' x='238.71' y='-175.8'>server</text>
			<path stroke-dasharray='5,2' d='M75.69,-188.5C87.72,-191.87 102.15,-195.33 115.44,-197 139.94,-200.07 146.5,-200.07 171,-197 184.28,-195.33 198.71,-191.87 210.74,-188.5' />
			<path stroke-dasharray='5,2' d='M170.76,-172.84C182.2,-174.06 195.65,-175.5 207.48,-176.77' />
			<ellipse cx='238.71' cy='-88' rx='27' ry='18' />
			<text text-anchor='middle' x='238.71' y='-83.8'>bulb</text>
			<path stroke-dasharray='5,2' d='M160.5,-155.72C177.66,-140.67 204.52,-117.11 221.61,-102.12' />
			<ellipse cx='238.71' cy='-34' rx='31.45' ry='18' />
			<text text-anchor='middle' x='238.71' y='-29.8'>router</text>
			<path stroke-dasharray='5,2' d='M150.17,-152.21C158.49,-129.25 175.35,-88.94 199.49,-61 204.16,-55.59 210.14,-50.71 215.97,-46.63' />
			<ellipse cx='343.54' cy='-34' rx='37.23' ry='18' />
			<text text-anchor='middle' x='343.54' y='-29.8'>internet</text>
			<path d='M270,-34C281.38,-34 294.42,-34 306.28,-34' />
		</g>
	</svg>

	1. Set up Tailscale to route traffic from the VPN into the LAN.
	2. Enable packet forwarding inside the Linux kernel on the relay node.
	   This allows the relay node itself to route traffic from the VPN into the LAN.
	3. Enable _IP masquerading_ on the relay node.
	   This a form of Network Address Translation (NAT) to make traffic from the VPN to the LAN appear to come from the relay node.

	### Setting it up
	
	<ol>
		<li>
			<p>On the relay node, run:</p>
			<pre><code>$ sudo tailscale up -advertise-routes=192.168.16.0/24</code></pre>
		</li>

		<li>
			<p>Go to the <a href='https://login.tailscale.com/admin/machines'>Tailscale admin console</a> and authorize subnet routes for the relay node.</p>
		</li>

		<li>
			<p>Back on the relay node, enable IP forwarding:</p>
			<pre><code>$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward</code></pre>
		</li>

		<li>
			<p>Enable IP masquerading for the _LAN-facing_ interfaces:</p>
			<pre><code>$ sudo nft add rule ip nat POSTROUTING oifname "enp2s0" counter masquerade</code></pre>
			<p>Alternatively, for iptables:</p>
			<pre><code>$ sudo iptables -t nat -A POSTROUTING -j MASQUERADE -o enp2s0</code></pre>
		</li>

		<li>
			<p>Confirm it works by pinging a machine on your LAN from a machine that's not, for example pinging <code>192.168.16.1</code> from a phone with the Tailscale VPN on mobile data.</p>
		</li>
	</ol>

	### Making it persistent

	To make enable IP forwarding on boot:

	```sh
	$ cat /etc/sysctl.d/50-forwarding.conf
	net.ipv4.ip_forward=1
	```

	To enable NAT on boot with nftables, add the following to `/etc/nftables.conf`:

	```
	table ip tailscale_nat {
		chain postrouting {
			type nat hook postrouting priority 100; policy accept;
			oifname "enp2s0" masquerade
		}
	}
	```

	Reboot the relay node and confirm that it all still works.
	{% endmarkdown %}
	</article>
{% endblock %}