diff --git a/cmd/nginx-auth/README.md b/cmd/nginx-auth/README.md index ec6d6527f..66b7cd963 100644 --- a/cmd/nginx-auth/README.md +++ b/cmd/nginx-auth/README.md @@ -117,10 +117,32 @@ header. The `Tailscale-Tailnet` header can help you identify which tailnet the session is coming from. If you are using node sharing, this can help you make sure that -you aren't giving administrative access to people outside your tailnet. You will -need to be sure to check this in your application code. If you use OpenResty, -you may be able to do more complicated access controls than you can with NGINX -alone. +you aren't giving administrative access to people outside your tailnet. + +### Allow Requests From Only One Tailnet + +If you want to prevent node sharing from allowing users to access a service, add +the `Expected-Tailnet` header to your auth request: + +```nginx +location /auth { + # ... + proxy_set_header Expected-Tailnet "tailscale.com"; +} +``` + +If a user from a different tailnet tries to use that service, this will return a +generic "forbidden" error page: + +```html + +403 Forbidden + +

403 Forbidden

+
nginx/1.18.0 (Ubuntu)
+ + +``` ## Building diff --git a/cmd/nginx-auth/deb/postinst.sh b/cmd/nginx-auth/deb/postinst.sh new file mode 100755 index 000000000..d352a8488 --- /dev/null +++ b/cmd/nginx-auth/deb/postinst.sh @@ -0,0 +1,14 @@ +if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then + deb-systemd-helper unmask 'tailscale.nginx-auth.socket' >/dev/null || true + if deb-systemd-helper --quiet was-enabled 'tailscale.nginx-auth.socket'; then + deb-systemd-helper enable 'tailscale.nginx-auth.socket' >/dev/null || true + else + deb-systemd-helper update-state 'tailscale.nginx-auth.socket' >/dev/null || true + fi + + if systemctl is-active tailscale.nginx-auth.socket >/dev/null; then + systemctl --system daemon-reload >/dev/null || true + deb-systemd-invoke stop 'tailscale.nginx-auth.service' >/dev/null || true + deb-systemd-invoke restart 'tailscale.nginx-auth.socket' >/dev/null || true + fi +fi diff --git a/cmd/nginx-auth/deb/postrm.sh b/cmd/nginx-auth/deb/postrm.sh new file mode 100755 index 000000000..4bce86139 --- /dev/null +++ b/cmd/nginx-auth/deb/postrm.sh @@ -0,0 +1,19 @@ +#!/bin/sh +set -e +if [ -d /run/systemd/system ] ; then + systemctl --system daemon-reload >/dev/null || true +fi + +if [ -x "/usr/bin/deb-systemd-helper" ]; then + if [ "$1" = "remove" ]; then + deb-systemd-helper mask 'tailscale.nginx-auth.socket' >/dev/null || true + deb-systemd-helper mask 'tailscale.nginx-auth.service' >/dev/null || true + fi + + if [ "$1" = "purge" ]; then + deb-systemd-helper purge 'tailscale.nginx-auth.socket' >/dev/null || true + deb-systemd-helper unmask 'tailscale.nginx-auth.socket' >/dev/null || true + deb-systemd-helper purge 'tailscale.nginx-auth.service' >/dev/null || true + deb-systemd-helper unmask 'tailscale.nginx-auth.service' >/dev/null || true + fi +fi diff --git a/cmd/nginx-auth/deb/prerm.sh b/cmd/nginx-auth/deb/prerm.sh new file mode 100755 index 000000000..e4becd170 --- /dev/null +++ b/cmd/nginx-auth/deb/prerm.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e +if [ "$1" = "remove" ]; then + if [ -d /run/systemd/system ]; then + deb-systemd-invoke stop 'tailscale.nginx-auth.service' >/dev/null || true + deb-systemd-invoke stop 'tailscale.nginx-auth.socket' >/dev/null || true + fi +fi diff --git a/cmd/nginx-auth/mkdeb.sh b/cmd/nginx-auth/mkdeb.sh index 2bdf41c48..c47ec2522 100755 --- a/cmd/nginx-auth/mkdeb.sh +++ b/cmd/nginx-auth/mkdeb.sh @@ -4,20 +4,28 @@ set -e CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o tailscale.nginx-auth . +VERSION=0.1.1 + mkpkg \ - --out tailscale-nginx-auth-0.1.0-amd64.deb \ + --out=tailscale-nginx-auth-${VERSION}-amd64.deb \ --name=tailscale-nginx-auth \ - --version=0.1.0 \ - --type=deb\ + --version=${VERSION} \ + --type=deb \ --arch=amd64 \ + --postinst=deb/postinst.sh \ + --postrm=deb/postrm.sh \ + --prerm=deb/prerm.sh \ --description="Tailscale NGINX authentication protocol handler" \ - --files=./tailscale.nginx-auth:/usr/sbin/tailscale.nginx-auth,./tailscale.nginx-auth.socket:/lib/systemd/system/tailscale.nginx-auth.socket,./tailscale.nginx-auth.service:/lib/systemd/system/tailscale.nginx-auth.service + --files=./tailscale.nginx-auth:/usr/sbin/tailscale.nginx-auth,./tailscale.nginx-auth.socket:/lib/systemd/system/tailscale.nginx-auth.socket,./tailscale.nginx-auth.service:/lib/systemd/system/tailscale.nginx-auth.service,./README.md:/usr/share/tailscale/nginx-auth/README.md mkpkg \ - --out tailscale-nginx-auth-0.1.0-amd64.rpm \ + --out=tailscale-nginx-auth-${VERSION}-amd64.rpm \ --name=tailscale-nginx-auth \ - --version=0.1.0 \ + --version=${VERSION} \ --type=rpm \ --arch=amd64 \ + --postinst=rpm/postinst.sh \ + --postrm=rpm/postrm.sh \ + --prerm=rpm/prerm.sh \ --description="Tailscale NGINX authentication protocol handler" \ - --files=./tailscale.nginx-auth:/usr/sbin/tailscale.nginx-auth,./tailscale.nginx-auth.socket:/lib/systemd/system/tailscale.nginx-auth.socket,./tailscale.nginx-auth.service:/lib/systemd/system/tailscale.nginx-auth.service + --files=./tailscale.nginx-auth:/usr/sbin/tailscale.nginx-auth,./tailscale.nginx-auth.socket:/lib/systemd/system/tailscale.nginx-auth.socket,./tailscale.nginx-auth.service:/lib/systemd/system/tailscale.nginx-auth.service,./README.md:/usr/share/tailscale/nginx-auth/README.md diff --git a/cmd/nginx-auth/nginx-auth.go b/cmd/nginx-auth/nginx-auth.go index a64df80cc..439dd3e6d 100644 --- a/cmd/nginx-auth/nginx-auth.go +++ b/cmd/nginx-auth/nginx-auth.go @@ -17,6 +17,7 @@ import ( "net" "net/http" "net/netip" + "net/url" "os" "strings" @@ -75,6 +76,12 @@ func main() { return } + if expectedTailnet := r.Header.Get("Expected-Tailnet"); expectedTailnet != "" && expectedTailnet != tailnet { + w.WriteHeader(http.StatusForbidden) + log.Printf("user is part of tailnet %s, wanted: %s", tailnet, url.QueryEscape(expectedTailnet)) + return + } + h := w.Header() h.Set("Tailscale-Login", strings.Split(info.UserProfile.LoginName, "@")[0]) h.Set("Tailscale-User", info.UserProfile.LoginName) diff --git a/cmd/nginx-auth/rpm/postinst.sh b/cmd/nginx-auth/rpm/postinst.sh new file mode 100755 index 000000000..e69de29bb diff --git a/cmd/nginx-auth/rpm/postrm.sh b/cmd/nginx-auth/rpm/postrm.sh new file mode 100755 index 000000000..3d0abfb19 --- /dev/null +++ b/cmd/nginx-auth/rpm/postrm.sh @@ -0,0 +1,9 @@ +# $1 == 0 for uninstallation. +# $1 == 1 for removing old package during upgrade. + +systemctl daemon-reload >/dev/null 2>&1 || : +if [ $1 -ge 1 ] ; then + # Package upgrade, not uninstall + systemctl stop tailscale.nginx-auth.service >/dev/null 2>&1 || : + systemctl try-restart tailscale.nginx-auth.socket >/dev/null 2>&1 || : +fi diff --git a/cmd/nginx-auth/rpm/prerm.sh b/cmd/nginx-auth/rpm/prerm.sh new file mode 100755 index 000000000..1f198d829 --- /dev/null +++ b/cmd/nginx-auth/rpm/prerm.sh @@ -0,0 +1,9 @@ +# $1 == 0 for uninstallation. +# $1 == 1 for removing old package during upgrade. + +if [ $1 -eq 0 ] ; then + # Package removal, not upgrade + systemctl --no-reload disable tailscale.nginx-auth.socket > /dev/null 2>&1 || : + systemctl stop tailscale.nginx-auth.socket > /dev/null 2>&1 || : + systemctl stop tailscale.nginx-auth.service > /dev/null 2>&1 || : +fi