RouterOS 7.6, Tailscale 1.32.0.
Add container registry option.
Container password as env option.
Enable upgrade functionality using Tailscale API.
This commit is contained in:
Frank Edwards 2022-10-25 18:52:32 +10:00
parent 0c26e89f66
commit c7f5f36486
5 changed files with 107 additions and 45 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
tailscale/
build-multi.sh
tailscale.tar

View file

@ -26,6 +26,18 @@ WORKDIR /go/src/tailscale
COPY tailscale/go.mod tailscale/go.sum ./ COPY tailscale/go.mod tailscale/go.sum ./
RUN go mod download RUN go mod download
# Pre-build some stuff before the following COPY line invalidates the Docker cache.
RUN go install \
github.com/aws/aws-sdk-go-v2/aws \
github.com/aws/aws-sdk-go-v2/config \
gvisor.dev/gvisor/pkg/tcpip/adapters/gonet \
gvisor.dev/gvisor/pkg/tcpip/stack \
golang.org/x/crypto/ssh \
golang.org/x/crypto/acme \
nhooyr.io/websocket \
github.com/mdlayher/netlink \
golang.zx2c4.com/wireguard/device
COPY tailscale/. . COPY tailscale/. .
# see build.sh # see build.sh
@ -43,21 +55,17 @@ RUN GOARCH=$TARGETARCH go install -ldflags="\
-X tailscale.com/version.GitCommit=$VERSION_GIT_HASH" \ -X tailscale.com/version.GitCommit=$VERSION_GIT_HASH" \
-v ./cmd/tailscale ./cmd/tailscaled -v ./cmd/tailscale ./cmd/tailscaled
FROM ghcr.io/tailscale/alpine-base:3.16 FROM alpine:3.16
# Set password RUN apk add --no-cache ca-certificates iptables iproute2 bash openssh curl jq
ARG TAILSCALE_PASSWORD="Pm36g58CzaLK"
RUN echo "root:$TAILSCALE_PASSWORD" | chpasswd
RUN apk add --no-cache ca-certificates iptables iproute2 bash sudo openssh
RUN ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa RUN ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
RUN ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa RUN ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa
COPY --from=build-env /go/bin/* /usr/local/bin/ COPY --from=build-env /go/bin/* /usr/local/bin/
ADD sshd_config /etc/ssh/ COPY sshd_config /etc/ssh/
COPY tailscale.sh /usr/local/bin
EXPOSE 22 EXPOSE 22
ADD tailscale.sh /usr/local/bin
CMD ["/usr/local/bin/tailscale.sh"] CMD ["/usr/local/bin/tailscale.sh"]

View file

@ -1,8 +1,8 @@
# Tailscale for Mikrotik Container # Tailscale for Mikrotik Container
This project provides the build and configuration information to run [Tailscale](https://tailscale.com) in [Mikrotik Container](https://help.mikrotik.com/docs/display/ROS/Container). Container is MikroTik's own implementation of Docker(TM), allowing users to run containerized environments within RouterOS. This project provides build and configuration information to run [Tailscale](https://tailscale.com) in [Mikrotik Container](https://help.mikrotik.com/docs/display/ROS/Container). Container is Mikrotik's own implementation of Docker(TM), allowing users to run containerized environments within RouterOS.
This project is recommended for research and testing purposes only. Running Container currently requires installing the development branch of RouterOS and is unsupported for production use. Testing indicates there are also significant performance impacts: running a unidirectional IPerf UDP test of 50 Mbps via the container on a Mikrotik hAP ac3 consumes ~75% of the router's CPU. This project is only recommended for research and testing purposes. Testing indicates there are significant performance hurdles: running a unidirectional IPerf UDP test of 50 Mbps via the container on a Mikrotik hAP ac3 consumes ~75% of the router's CPU.
## Instructions ## Instructions
@ -15,36 +15,32 @@ A WAN interface is configured as per default configuration on **ether1** for con
### Build the Docker Image ### Build the Docker Image
Note this step is only required if you are uploading an image to your router. See Configuration Step 6.
The build script uses [Docker Buildx](https://docs.docker.com/buildx/working-with-buildx/). The build script uses [Docker Buildx](https://docs.docker.com/buildx/working-with-buildx/).
1. In `build.sh` set the PLATFORM shell script variable as required for the target router CPU - see [https://mikrotik.com/products/matrix](https://mikrotik.com/products/matrix) 1. In `build.sh` set the PLATFORM shell script variable as required for the target router CPU - see [https://mikrotik.com/products/matrix](https://mikrotik.com/products/matrix)
2. In `Dockerfile` set the following argument.
| Argument | Description | 2. Run `./build.sh` to build the image. The build process will generate a container image archive file **`tailscale.tar`**
| ------------------ | ---------------------- |
| TAILSCALE_PASSWORD | Password for root user |
3. Run `./build.sh` to build the image. The build process will generate a container image file **`tailscale.tar`**
### Configure the Router ### Configure the Router
The router must be be running RouterOS v7.5 or later with the container package loaded; this section follows the Mikrotik Container documentation with additional steps to route the LAN subnet via the tailscale container. The router must be be running RouterOS v7.6 or later with the container package loaded; this section follows the Mikrotik Container documentation with additional steps to route the LAN subnet via the tailscale container.
1. Upload the `tailscale.tar` file to your router. Below we will assume the image is located at `disk1/tailscale.tar`
2. Enable container mode, and reboot. 1. Enable container mode, and reboot.
``` ```
/system/device-mode/update container=yes /system/device-mode/update container=yes
``` ```
3. Create a veth interface for the container. 2. Create a veth interface for the container.
``` ```
/interface/veth add name=veth1 address=172.17.0.2/16 gateway=172.17.0.1 /interface/veth add name=veth1 address=172.17.0.2/16 gateway=172.17.0.1
``` ```
4. Create a bridge for the container and add veth1 as a port. 3. Create a bridge for the container and add veth1 as a port.
``` ```
/interface/bridge add name=dockers /interface/bridge add name=dockers
@ -52,49 +48,60 @@ The router must be be running RouterOS v7.5 or later with the container package
/interface/bridge/port add bridge=dockers interface=veth1 /interface/bridge/port add bridge=dockers interface=veth1
``` ```
5. Enable routing from the LAN to the Tailscale Network 4. Enable routing from the LAN to the Tailscale Network
``` ```
/ip/route/add dst-address=100.64.0.0/10 gateway=172.17.0.2 /ip/route/add dst-address=100.64.0.0/10 gateway=172.17.0.2
``` ```
6. Create environment variables as per the list below. 5. Add environment variables as per the list below.
| Variable | Description | Comment | | Variable | Description | Comment |
| ----------------- | --------------------------------------------- | -------------------------------------------- | | ----------------- | --------------------------------------------- | -------------------------------------------- |
| AUTH_KEY | Tailscale reusable key | Generate the key from the tailscale console. | | PASSWORD | System root user password | |
| DOMAIN | Tailscale domain | |
| AUTH_KEY | Tailscale reusable key | Generate from the tailscale console |
| API_KEY | Tailscale API key | See Upgrading section below |
| ADVERTISE_ROUTES | Comma-separated list of routes to advertise | | | ADVERTISE_ROUTES | Comma-separated list of routes to advertise | |
| CONTAINER_GATEWAY | The Container bridge IP address on the router | | | CONTAINER_GATEWAY | The container bridge IP address on the router | |
| TAILSCALE_ARGS | Additional arguments passed to tailscale | Optional |
``` ```
/container/envs /container/envs
add name="tailscale" key="PASSWORD" value="xxxxxxxxxxxxxx"
add name="tailscale" key="DOMAIN" value="example.com"
add name="tailscale" key="AUTH_KEY" value="tskey-xxxxxxxxxxxxxxxxxxxxxxxx" add name="tailscale" key="AUTH_KEY" value="tskey-xxxxxxxxxxxxxxxxxxxxxxxx"
add name="tailscale" key="API_KEY" value="tskey-xxxxxxxxxxxxxxxxxxxxxxxx"
add name="tailscale" key="ADVERTISE_ROUTES" value="192.168.88.0/24" add name="tailscale" key="ADVERTISE_ROUTES" value="192.168.88.0/24"
add name="tailscale" key="CONTAINER_GATEWAY" value="172.17.0.1" add name="tailscale" key="CONTAINER_GATEWAY" value="172.17.0.1"
add name="tailscale" key="TAILSCALE_ARGS" value="--accept-routes"
``` ```
7. Create a container from the tailscale.tar image 6. Create the container
The container can be created via a registry or using the `tailscale.tar` file.
a. Container registry
Configure the registry URL and add the container.
``` ```
/container add file=disk1/tailscale.tar interface=veth1 envlist=tailscale root-dir=disk1/containers/tailscale hostname=mikrotik dns=8.8.4.4,8.8.8.8 /container/config
set registry-url=https://ghcr.io tmpdir=disk1/pull
/container add remote-image=fluent-networks/tailscale-mikrotik:latest interface=veth1 envlist=tailscale root-dir=disk1/containers/tailscale start-on-boot=yes hostname=mikrotik dns=8.8.4.4,8.8.8.8
``` ```
If you want to see the container output in the router log add `logging=yes` b. Tar archive file
8. Optional - configure the container to startup on boot. Upload the `tailscale.tar` file to your router. Below we will assume the image is located at `disk1/tailscale.tar`
``` ```
/system/script /container add file=disk1/tailscale.tar interface=veth1 envlist=tailscale root-dir=disk1/containers/tailscale start-on-boot=yes hostname=mikrotik dns=8.8.4.4,8.8.8.8
add name="tailscale" source= {
:delay 60s
/container
start [find tag="tailscale:tailscale"]
}
/system/schedule
add name=tailscale on-event=tailscale start-time=startup interval=0
``` ```
If you want to see the container output in the router log add `logging=yes` to the container add command.
### Start the Container ### Start the Container
Ensure the container has been extracted and added by verifying `status=stopped` using `/container/print` Ensure the container has been extracted and added by verifying `status=stopped` using `/container/print`
@ -105,10 +112,23 @@ Ensure the container has been extracted and added by verifying `status=stopped`
### Verify Connectivity ### Verify Connectivity
In the Tailscale console, verify the router is authenticated and enable the subnet routes. Your tailscale hosts should now be able to reach the router's LAN subnet. In the Tailscale console, check the router is authenticated and enable the subnet routes. Your tailscale hosts should now be able to reach the router's LAN subnet.
The container exposes a SSH server for management purposes using root credentials, and can be accessed via the router's tailscale address or the veth interface address. The container exposes a SSH server for management purposes using root credentials, and can be accessed via the router's tailscale address or the veth interface address.
## Upgrading
To upgrade, first stop and remove the container.
```
/container/stop 0
/container/remove 0
```
Create a new container as per Step 6. The tailscale.sh script detects if the tailscale machine exists and removes it using the Tailscale API. A new machine is then created with the same hostname.
In the Tailscale console, check the router is authenticated and enable the subnet routes.
## Contributing ## Contributing
We welcome suggestions and feedback from people interested in integrating Tailscale on the RouterOS platform. Please send a PR or create an issue if you're having any problems. We welcome suggestions and feedback from people interested in integrating Tailscale on the RouterOS platform. Please send a PR or create an issue if you're having any problems.

View file

@ -25,21 +25,26 @@
# https://mikrotik.com/products/matrix # https://mikrotik.com/products/matrix
# #
PLATFORM="linux/arm/v7" PLATFORM="linux/arm/v7"
TAILSCALE_VERSION=1.32.0
VERSION=0.1.6
set -eu set -eu
rm -f tailscale.tar
if [ ! -d ./tailscale/.git ] if [ ! -d ./tailscale/.git ]
then then
git clone https://github.com/tailscale/tailscale.git git -c advice.detachedHead=false clone https://github.com/tailscale/tailscale.git --branch v$TAILSCALE_VERSION
fi fi
cd tailscale && eval $(./build_dist.sh shellvars) && cd .. cd tailscale && eval $(./build_dist.sh shellvars) && cd ..
docker buildx build \ docker buildx build \
--no-cache \
--build-arg VERSION_LONG=$VERSION_LONG \ --build-arg VERSION_LONG=$VERSION_LONG \
--build-arg VERSION_SHORT=$VERSION_SHORT \ --build-arg VERSION_SHORT=$VERSION_SHORT \
--build-arg VERSION_GIT_HASH=$VERSION_GIT_HASH \ --build-arg VERSION_GIT_HASH=$VERSION_GIT_HASH \
--platform $PLATFORM \ --platform $PLATFORM \
-t tailscale:tailscale . --load -t ghcr.io/fluent-networks/tailscale-mikrotik:$VERSION .
docker save -o tailscale.tar tailscale:tailscale docker save -o tailscale.tar ghcr.io/fluent-networks/tailscale-mikrotik:$VERSION

View file

@ -1,11 +1,19 @@
#!/bin/bash #!/bin/bash
set -m
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
# Prepare run dir # Prepare run dir
if [ ! -d "/var/run/sshd" ]; then if [ ! -d "/var/run/sshd" ]; then
mkdir -p /var/run/sshd mkdir -p /var/run/sshd
fi fi
set -m # Set root password
echo "root:${PASSWORD}" | chpasswd
# Install routes # Install routes
IFS=',' read -ra SUBNETS <<< "${ADVERTISE_ROUTES}" IFS=',' read -ra SUBNETS <<< "${ADVERTISE_ROUTES}"
@ -13,11 +21,28 @@ for s in "${SUBNETS[@]}"; do
ip route add "$s" via "${CONTAINER_GATEWAY}" ip route add "$s" via "${CONTAINER_GATEWAY}"
done done
# Check if this is first-time container startup
if [ ! -f "/var/run/tailscale.sh.pid" ]; then
# Delete all the old devices with this hostname.
IDS=$(curl -sSL "https://api.tailscale.com/api/v2/domain/${DOMAIN}/devices" -u "${API_KEY}:" | jq -r '.[][] | select(.hostname == "'${HOSTNAME}'") | .id' || echo "")
while IFS= read -r id; do
if [[ ! -z "$id" ]]; then
echo "deleting tailscale device: $id";
curl -sSL -XDELETE -u "${API_KEY}:" "https://api.tailscale.com/api/v2/device/$id";
fi
done <<EOL
$IDS
EOL
fi
echo $$ >/var/run/tailscale.sh.pid
# Start tailscaled and bring tailscale up # Start tailscaled and bring tailscale up
/usr/local/bin/tailscaled & /usr/local/bin/tailscaled &
until /usr/local/bin/tailscale up \ until /usr/local/bin/tailscale up \
--authkey=${AUTH_KEY} \ --reset --authkey=${AUTH_KEY} \
--advertise-routes="${ADVERTISE_ROUTES}" --advertise-routes="${ADVERTISE_ROUTES}" \
${TAILSCALE_ARGS}
do do
sleep 0.1 sleep 0.1
done done