|
| 1 | +# dialtun |
| 2 | + |
| 3 | +**Dynamic routing of public HTTPS endpoints to internal ports on your |
| 4 | +Tailscale-connected development machines.** |
| 5 | + |
| 6 | +`dialtun` maps server names in the form `SERVICE-MACHINE.example.com` (where |
| 7 | +`example.com` is any domain you control) to internal machines on your Tailnet. |
| 8 | +`MACHINE` is the exact name of a machine in the Tailscale network. `SERVICE` is |
| 9 | +mapped to a port number by referencing the labels on a (US-based) telephone |
| 10 | +dialpad: |
| 11 | + |
| 12 | +<pre style="font-family: Menlo; line-height: 1.2em;"> |
| 13 | +┌─────────────────────────┐ |
| 14 | +│ ┌─────┐ ┌─────┐ ┌─────┐ │ |
| 15 | +│ │ │ │ ABC │ │ DEF │ │ |
| 16 | +│ │ 1 │ │ 2 │ │ 3 │ │ |
| 17 | +│ └─────┘ └─────┘ └─────┘ │ |
| 18 | +│ ┌─────┐ ┌─────┐ ┌─────┐ │ |
| 19 | +│ │ GHI │ │ JKL │ │ MNO │ │ |
| 20 | +│ │ 4 │ │ 5 │ │ 6 │ │ |
| 21 | +│ └─────┘ └─────┘ └─────┘ │ |
| 22 | +│ ┌─────┐ ┌─────┐ ┌─────┐ │ |
| 23 | +│ │PQRS │ │ TUV │ │WXYZ │ │ |
| 24 | +│ │ 7 │ │ 8 │ │ 9 │ │ |
| 25 | +│ └─────┘ └─────┘ └─────┘ │ |
| 26 | +│ ┌─────┐ │ |
| 27 | +│ │ │ │ |
| 28 | +│ │ 0 │ │ |
| 29 | +│ └─────┘ │ |
| 30 | +└─────────────────────────┘ |
| 31 | +</pre> |
| 32 | + |
| 33 | +A base port number -- 64000, by default -- is added to the first three numbers |
| 34 | +of the service name. The final result is that a domain name like |
| 35 | +"agendas-devbox1.dev.example.com" would map to port 64243 (64000 + 243) on the |
| 36 | +"devbox1" machine on your Tailnet. |
| 37 | + |
| 38 | +## Important Security Warning |
| 39 | + |
| 40 | +`dialtun` does _not_ authenticate incoming connections. Any port in the |
| 41 | +configured range (64000-64999, by default) is accessible on the public Internet. |
| 42 | +Tailscale ACLs are still consulted, but if you open port 64000 on your machine, |
| 43 | +then you should expect that random machines on the Internet _will_ connect to |
| 44 | +that port. |
| 45 | + |
| 46 | +In other words, goal of `dialtun` is not to create a _secure_ way to talk to |
| 47 | +your internal services -- use normal Tailscale sharing and ACLs for that -- the |
| 48 | +goal is agility and flexibility. The _assumption_ is that whatever you are |
| 49 | +exposing has its own auth model, or is a simple website that is not secret. |
| 50 | + |
| 51 | +## Setup Instructions |
| 52 | + |
| 53 | +### Create Tailscale ACL Tag |
| 54 | + |
| 55 | +Add an ACL tag to your |
| 56 | +[Tailscale Access Controls](https://login.tailscale.com/admin/acls): |
| 57 | + |
| 58 | +1. Add a new tag to the `tagOwners` list, something like this: |
| 59 | + |
| 60 | + ```json |
| 61 | + // ACL tags. |
| 62 | + "tagOwners": { |
| 63 | + "tag:dialtun": [], |
| 64 | + }, |
| 65 | + ``` |
| 66 | + |
| 67 | +2. Add a section for `dialtun` to the `acls` block (assuming you keep the |
| 68 | + default port range of 64000-64999): |
| 69 | + |
| 70 | + ```json |
| 71 | + "acls": [ |
| 72 | + // ... |
| 73 | + |
| 74 | + // dialtun can access dev server ports on all machines. |
| 75 | + { |
| 76 | + "action": "accept", |
| 77 | + "src": ["tag:dialtun"], |
| 78 | + "dst": ["autogroup:members:64000-64999"], |
| 79 | + }, |
| 80 | + |
| 81 | + // ... |
| 82 | + ], |
| 83 | + ``` |
| 84 | + |
| 85 | +3. (Optionally) Add an ACL test to verify that `dialtun` can access the dev |
| 86 | + server ports, but not any other ports (such as SSH) on the dev machines (this |
| 87 | + assumes a dev machine of "devbox1"): |
| 88 | + |
| 89 | + ```json |
| 90 | + "acls": [ |
| 91 | + // ... |
| 92 | + |
| 93 | + // dialtun can access the dev ports on all machines (but not SSH). |
| 94 | + { |
| 95 | + "src": "tag:dialtun", |
| 96 | + "accept": ["devbox1:64243", "devbox1:64999"], |
| 97 | + "deny": ["devbox1:22"], |
| 98 | + }, |
| 99 | + |
| 100 | + // ... |
| 101 | + ], |
| 102 | + ``` |
| 103 | + |
| 104 | +### Create Tailscale Auth Key |
| 105 | + |
| 106 | +Create a Tailscale auth key. The key should be Reusable, Ephemeral, and include |
| 107 | +the `dialtun` tag that you defined earlier. |
| 108 | + |
| 109 | +### Create `dialtun` App in Fly.io |
| 110 | + |
| 111 | +_Create_ (but do not yet deploy, since we need to add secrets) the `dialtun` app |
| 112 | +on Fly.io: |
| 113 | + |
| 114 | +```shell |
| 115 | +$ flyctl launch --build-only --image ghcr.io/malyn/dialtun:latest |
| 116 | +``` |
| 117 | + |
| 118 | +You can choose an app name, or go with the auto-generated default. The app name |
| 119 | +will not be used, assuming that you create the `CNAME` mapping in the next step. |
| 120 | + |
| 121 | +### Create Wildcard TLS Certificate |
| 122 | + |
| 123 | +Add an IP address to your app, then create a _wildcard_ TLS certificate; both |
| 124 | +will require adding DNS entries to your DNS server. This is documented on the |
| 125 | +Fly.io |
| 126 | +[Custom Domains and SSL Certificates page](https://fly.io/docs/app-guides/custom-domains-with-fly/). |
| 127 | + |
| 128 | +### Add Tailscale Auth Key to Fly.io App |
| 129 | + |
| 130 | +Add the Tailscale auth key secret to the app: |
| 131 | + |
| 132 | +```shell |
| 133 | +$ flyctl secrets import |
| 134 | +TS_AUTHKEY=tskey-auth-... |
| 135 | +<Ctrl-D> |
| 136 | +``` |
| 137 | + |
| 138 | +Using `flyctl secrets import` means that your secrets will not show up in your |
| 139 | +shell's command history. Press `Control-D` on a blank line to complete the |
| 140 | +input. `flyctl` will respond with "Secrets are staged for the first deployment" |
| 141 | + |
| 142 | +### Deploy the Fly.io App |
| 143 | + |
| 144 | +Deploy the app: |
| 145 | + |
| 146 | +```shell |
| 147 | +$ flyctl deploy |
| 148 | +``` |
| 149 | + |
| 150 | +That's it! You can then access internal machines using `dialtun` URLs. |
0 commit comments