- Vrealmatic
- Ubuntu Server
- Tailscale
Tailscale na Ubuntu Serveru: bezpečná instalace a SSH přístup
Návod co nejbezpečněji nainstaluje a nastaví Tailscale na Ubuntu Serveru (LTS) a zpřístupní přes něj SSH. Z internetu SSH na konci zavře; u serveru v lokální síti volitelně ponechá SSH z LAN jako záložní cestu. Tailscale tu slouží jen jako privátní kanál pro SSH: žádný exit node, subnet router, Serve, Funnel ani Tailscale SSH. Pokud na serveru zároveň běží Mullvad VPN s kill switchem, navazuje doplněk na konci článku.
Ověřeno proti oficiální dokumentaci k 2. 10. 2026: Tailscale 1.102.x (stable), Ubuntu 24.04 LTS (noble) a 26.04 LTS (resolute), stránka Mullvadu o split tunnelingu na Linuxu (aktualizovaná 25. 4. 2024).

Placeholdery
V příkazech nahraďte tyto hodnoty svými.
| Placeholder | Význam | Příklad / kde ho zjistit |
|---|---|---|
<ADMIN_USER> | Linuxový uživatel, pod kterým se přihlašujete přes SSH | vladimir |
<TAILNET_USER> | Vaše identita (login) v tailnetu | vy@example.com |
<SERVER_TS_NAME> | Jméno serveru v tailnetu (MagicDNS) | srv01 |
<TAILSCALE_IP_SERVER> | Tailscale IPv4 serveru | tailscale ip -4 na serveru |
<TAILSCALE_IP_PC> | Tailscale IPv4 vašeho PC | tailscale ip -4 na PC |
<TAILSCALE_IP_NB> | Tailscale IPv4 notebooku | tailscale ip -4 na notebooku |
<SSH_PORT> | Port, na kterém běží sshd (výchozí 22, změna viz průvodce Ubuntu Serverem) | sudo sshd -T | grep -i '^port' |
<PUBLIC_IP> | Veřejná IP serveru, ve scénáři B veřejná IP routeru (pro test, že SSH port je z internetu zavřený) | panel poskytovatele / router |
<LAN_SUBNET> | Lokální síť, ze které zůstane SSH povolené (jen scénář B) | 192.168.88.0/24, ip -4 route na serveru |
<LAN_IP_SERVER> | IP serveru v lokální síti (jen scénář B) | ip -4 addr show na serveru |
<CODENAME> | Codename Ubuntu | lsb_release -cs → noble, resolute |
<ZEME> | Kód země pro výběr Mullvad exit nodu (jen doplněk) | CZ, DE |
<MULLVAD_EXIT_NODE> | Hostname Mullvad exit nodu (jen doplněk) | tailscale exit-node list |
1. Přehled architektury
SSH na serveru zůstává běžný OpenSSH na portu <SSH_PORT>; Tailscale jen dopraví TCP spojení z vašeho PC přes šifrovaný WireGuard tunel na rozhraní tailscale0. Paket pak prochází třemi nezávislými vrstvami a zahodit ho může kterákoli z nich:
- Tailscale policy (grants/ACL) – vynucuje ji
tailscaledna serveru ještě před vložením paketu dotailscale0. Povolí jen vašeho uživatele natcp:<SSH_PORT>. - UFW – lokální firewall v tabulkách
ip filter/ip6 filter(iptables-nft). Povolí SSH port jen natailscale0, ve scénáři B navíc z lokální sítě. - OpenSSH – přihlášení pouze klíčem, bez roota, bez hesla (SSH klíče).
SSH port je na konci z internetu zavřený, takže server z internetu SSH vůbec nenabízí. U serveru v lokální síti pod vaší správou zůstává SSH z LAN jako záložní cesta (scénáře v kapitole 2). Spojení na internet navazuje jen tailscaled (koordinační server, DERP relay, UDP 41641), a to odchozí.
Tailscale tu slouží jen jako privátní kanál pro SSH: žádný exit node, subnet router, Serve, Funnel ani Tailscale SSH. Pokud na serveru zároveň běží Mullvad VPN s kill switchem, potřebujete navíc doplněk na konci článku – bez něj Mullvad provoz z tailscale0 zahodí.
2. Předpoklady, scénáře a záložní přístup
Předpoklady:
- Ubuntu Server 24.04 LTS nebo 26.04 LTS, uživatel
<ADMIN_USER>sesudo(správa uživatelů). - Funkční přihlášení SSH klíčem pro
<ADMIN_USER>a vypnuté přihlášení heslem i rootem podle článku SSH klíče (ověřené, ne jen nahrané doauthorized_keys). - SSH na portu
<SSH_PORT>– změnu výchozího portu 22 popisuje průvodce Ubuntu Serverem. Pokud port neměníte, dosaďte 22. - UFW se základními politikami podle průvodce, kapitola Nastavení Firewallu.
- Tailscale účet (tailnet) s vaším uživatelem přihlášeným přes identity provider; na PC/notebooku nainstalovaný a přihlášený klient.
- Během celé konfigurace mějte otevřenou jednu stávající SSH relaci a každou změnu testujte v druhé, nové relaci.
Scénáře nasazení
Co se na konci stane s SSH mimo Tailscale, záleží na tom, kde server běží a jaká mu zbude záložní cesta:
| Scénář | Typicky | Záložní přístup | SSH mimo tailscale0 |
|---|---|---|---|
| A – mimo váš dosah | VPS, server v datacentru, server v cizí síti | konzole poskytovatele (VNC, KVM, IPMI) | zavřít úplně |
| B – lokální síť pod vaší správou | server doma nebo ve firmě za vlastním routerem | SSH z LAN, fyzický přístup | povolit jen z <LAN_SUBNET>, z internetu zavřít |
Ve scénáři A nepovolujte SSH z privátní sítě datacentra – není vaše. Ve scénáři B nesmí být SSH port na routeru přesměrovaný do internetu (viz NAT na MikroTiku).
Pojistka: automatický rollback
Před rizikovým krokem si naplánujte „dead man's switch“, který za 10 minut SSH port znovu otevře. Když vše funguje, časovač zrušíte.
# naplánuje znovuotevření SSH portu za 10 minut (transientní systemd timer)
sudo systemd-run --unit=rollback-ssh --on-active=10min /usr/sbin/ufw allow <SSH_PORT>/tcp
# vše funguje → pojistku zrušte
sudo systemctl stop rollback-ssh.timerRuční rollback
Pokud přístup ztratíte, z konzole poskytovatele (ve scénáři B z LAN nebo u fyzické klávesnice) vraťte změny v tomto pořadí (každý krok jednotlivě, po každém zkuste SSH):
# 1) znovu otevřít SSH port
sudo ufw allow <SSH_PORT>/tcp
# 2) pokud je problém v přihlášení: vrátit poslední změnu v /etc/ssh/sshd_config
# nebo /etc/ssh/sshd_config.d/ a ověřit syntaxi
sudo sshd -t && sudo systemctl restart ssh
# 3) poslední možnost: vypnout firewall úplně
sudo ufw disableSe zapnutým Mullvadem viz rollback v doplňku.
3. Instalace Tailscale z APT repozitáře
Instalujeme ze stable repozitáře pkgs.tailscale.com bez curl | sh: klíč i .list stáhneme do dočasných souborů, zkontrolujeme a teprve pak nainstalujeme. Repozitář má k 2. 10. 2026 větve pro noble (24.04) i resolute (26.04), aktuální stable je 1.102.x.
Zjistěte codename systému (použije se v URL repozitáře):
CODENAME="$(lsb_release -cs)"; echo "$CODENAME"Stáhněte podpisový klíč repozitáře do dočasného souboru (formát noarmor = binární keyring, který APT čte přímo):
curl -fsSL "https://pkgs.tailscale.com/stable/ubuntu/${CODENAME}.noarmor.gpg" -o /tmp/tailscale-archive-keyring.gpgZkontrolujte obsah klíče bez importu do keyringu; long ID má končit 458CA832957F5868 a UID je „Tailscale Inc. (Package repository signing key) <info@tailscale.com>“:
gpg --show-keys --keyid-format long /tmp/tailscale-archive-keyring.gpgNainstalujte klíč do /usr/share/keyrings/ s vlastníkem root a právy 0644 (adresář nepatří do globální důvěry APT, klíč platí jen pro repozitář, který na něj ukáže přes signed-by):
sudo install -d -m 0755 /usr/share/keyrings
sudo install -m 0644 -o root -g root /tmp/tailscale-archive-keyring.gpg /usr/share/keyrings/tailscale-archive-keyring.gpgVytvořte .list soubor s vazbou signed-by na tento klíč (stejný obsah, jaký publikuje Tailscale):
printf '# Tailscale packages for ubuntu %s\ndeb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/ubuntu %s main\n' \
"$CODENAME" "$CODENAME" | sudo tee /etc/apt/sources.list.d/tailscale.listZkontrolujte výsledné soubory:
cat /etc/apt/sources.list.d/tailscale.list
ls -l /usr/share/keyrings/tailscale-archive-keyring.gpgOčekávaný obsah .list (pro noble):
# Tailscale packages for ubuntu noble
deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/ubuntu noble mainNainstalujte balíček a ověřte, že běží démon:
sudo apt update
sudo apt install tailscale
systemctl status tailscaled --no-pager
tailscale versionPo upgradu Ubuntu na další LTS změňte codename v .list i klíč (stáhněte <CODENAME>.noarmor.gpg pro nové vydání).
4. Připojení do tailnetu a tag tag:server
Server připojíme rovnou s tagem: tagované zařízení nepatří žádnému uživateli, má vypnutou expiraci klíče a v policy na něj lze cílit jako na roli. Tag jde přidělit jen tehdy, když je definovaný v tagOwners.
Krok 1 – definujte tag v policy. V admin konzoli (Access controls) doplňte do stávající policy jen sekci tagOwners; výchozí pravidla zatím ponechte, zpřísníme je v kapitole 7.
"tagOwners": {
"tag:server": ["<TAILNET_USER>"],
},Krok 2 – připojte server. Příkaz vypíše přihlašovací URL; otevřete ji na PC a přihlaste se jako <TAILNET_USER> (vlastník tagu).
sudo tailscale up --accept-dns=false --accept-routes=false --advertise-tags=tag:serverVýznam flagů:
--accept-dns=false– Tailscale nepřepíše/etc/resolv.conf/ systemd-resolved; server neřeší MagicDNS jména a jeho DNS zůstává pod vaší (případně Mullvadovou) kontrolou.--accept-routes=false– server nepřijme subnet routy jiných uzlů; na Linuxu je to výchozí stav, explicitně ho uvádíme kvůli čitelnosti.--advertise-tags=tag:server– identita zařízení bude tag, ne váš uživatel.
Flagy tailscale up se mezi spuštěními neukládají jako „diff“: pozdější tailscale up bez nich ohlásí chybu nebo je resetuje. Dodatečné změny dělejte přes tailscale set (např. sudo tailscale set --auto-update).
Krok 3 – pokud máte zapnutý Device approval, schvalte nový uzel v admin konzoli (Machines). Bez schválení server do tailnetu nepustí žádný provoz.
Krok 4 – ověřte stav a poznamenejte si IP:
tailscale status
tailscale ip -4 # → <TAILSCALE_IP_SERVER>V admin konzoli u serveru zkontrolujte, že má tag tag:server a u Key expiry je „Disabled“. Na PC ověřte SSH přes Tailscale (SSH port je zatím otevřený i mimo Tailscale):
ssh -p <SSH_PORT> <ADMIN_USER>@<TAILSCALE_IP_SERVER>Pokud na serveru běží Mullvad s kill switchem, tento test selže – nejdřív nastavte výjimku z doplňku a pak se sem vraťte.
5. OpenSSH hardening
Přihlášení pouze klíčem, zákaz hesla a roota včetně přepisů v /etc/ssh/sshd_config.d/ (např. 50-cloud-init.conf) nastavte podle článku SSH klíče › SSHD konfigurace. Tady jen ověříme výsledek a doplníme omezení na jednoho uživatele.
Doplněk – přihlásit se smí jen <ADMIN_USER>. Soubory v /etc/ssh/sshd_config.d/ Ubuntu načítá přes Include na začátku sshd_config; pokud už někde AllowUsers máte, upravte raději ten záznam:
echo 'AllowUsers <ADMIN_USER>' | sudo tee /etc/ssh/sshd_config.d/10-allowusers.confOvěřte syntaxi a efektivní hodnoty (sshd -T vypíše výslednou konfiguraci po zpracování všech include):
sudo sshd -t && echo OK
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|authenticationmethods|allowusers)'Restartujte službu (na Ubuntu 24.04+ je sshd socket-aktivovaný; restart ssh.service stávající relace neukončí):
sudo systemctl restart sshV nové relaci ověřte, že přihlášení klíčem funguje a heslo se nenabízí:
ssh -p <SSH_PORT> <ADMIN_USER>@<TAILSCALE_IP_SERVER>
ssh -p <SSH_PORT> -o PubkeyAuthentication=no -o PreferredAuthentications=password <ADMIN_USER>@<TAILSCALE_IP_SERVER> # má skončit „Permission denied (publickey)“sshd záměrně neomezujeme přes ListenAddress <TAILSCALE_IP_SERVER>: při startu systému tailscale0 ještě nemusí existovat a sshd by se nespustil. Omezení na rozhraní řeší UFW a Tailscale policy.
6. UFW a uzavření SSH mimo Tailscale
Výchozí politiky UFW (příchozí zakázat, odchozí povolit) nastavte podle průvodce, kapitola Aplikování výchozího nastavení pro UFW. Tady přidáme pravidlo pro tailscale0, ve scénáři B pravidlo pro LAN, a obecné pravidlo pro SSH port odebereme až po ověření.
Zjistěte současný stav (uvidíte existující pravidla, která možná chcete zachovat):
sudo ufw status verbosePovolte SSH přes Tailscale:
sudo ufw allow in on tailscale0 to any port <SSH_PORT> proto tcp comment 'SSH via Tailscale'Pokud UFW ještě neběží, dočasně ponechte SSH odevšad, aby zapnutí UFW nepřerušilo stávající relaci:
sudo ufw allow <SSH_PORT>/tcp comment 'TEMP SSH'
sudo ufw enable
sudo ufw status verboseZ PC ověřte SSH přes Tailscale (ssh -p <SSH_PORT> <ADMIN_USER>@<TAILSCALE_IP_SERVER>).
Jen scénář B – povolte SSH z lokální sítě jako záložní cestu a z jiného zařízení v LAN ji ověřte:
sudo ufw allow from <LAN_SUBNET> to any port <SSH_PORT> proto tcp comment 'SSH from LAN (fallback)'
# z PC v LAN:
ssh -p <SSH_PORT> <ADMIN_USER>@<LAN_IP_SERVER>Teprve pak odeberte obecné pravidlo.
sudo ufw delete allow <SSH_PORT>/tcp
# pokud jste dřív povolili profil OpenSSH:
sudo ufw delete allow OpenSSH
sudo ufw status numberedVe výpisu má zůstat <SSH_PORT>/tcp on tailscale0 (IPv4 a v6), ve scénáři B navíc <SSH_PORT>/tcp ALLOW IN <LAN_SUBNET>, plus případná pravidla jiných služeb, která jste zachovali.
Jak spolu UFW a Tailscale souvisí
tailscaled v režimu --netfilter-mode=on (výchozí) vkládá do ip filter na začátek řetězce INPUT skok do ts-input, který obsahuje iifname "tailscale0" accept. Tím je provoz z tailscale0 přijat ještě před řetězci UFW, takže na tomto rozhraní ve skutečnosti filtruje Tailscale policy (kapitola 7), ne UFW. Ověření:
sudo iptables -S INPUT | head -5
sudo iptables -S ts-inputVýchozí chování odpovídá doporučení Tailscale a s restriktivní policy je dostatečné. Pokud chcete, aby UFW bylo na tailscale0 druhou nezávislou bránou, spusťte Tailscale s --netfilter-mode=off (pak firewall pro Tailscale spravujete sami) a povolte UDP 41641 pro přímá P2P spojení:
sudo tailscale set --netfilter-mode=off
sudo ufw allow 41641/udp comment 'Tailscale direct'7. Tailscale admin konzole
Policy: jen můj uživatel na tag:server:<SSH_PORT>
Policy používá grants (nástupce acls; port je v poli ip, ne v dst). Výchozí stav bez grantu je deny, takže server jako tag:server nemá žádné povolení a nemůže iniciovat spojení nikam; odpovědi na povolená spojení Tailscale propouští stavově. Sekce ssh chybí, takže Tailscale SSH je vypnuté; chybí i autoApprovers, takže server nemůže inzerovat routy ani exit node.
{
// Kdo smí přidělit tag:server (Owner/Admin smí vždy).
"tagOwners": {
"tag:server": ["<TAILNET_USER>"],
},
// Jediné povolení v tailnetu: zařízení mého uživatele -> SSH na servery.
"grants": [
{
"src": ["<TAILNET_USER>"],
"dst": ["tag:server"],
"ip": ["tcp:<SSH_PORT>"],
},
],
// Bez sekce "ssh" (Tailscale SSH vypnuto) a bez "autoApprovers".
"tests": [
{
"src": "<TAILNET_USER>",
"accept": ["tag:server:<SSH_PORT>"],
"deny": ["tag:server:80", "tag:server:443"],
},
{
// Server nesmí iniciovat spojení na klienty.
"src": "tag:server",
"deny": ["<TAILSCALE_IP_PC>:22", "<TAILSCALE_IP_NB>:22"],
},
],
}Důsledky: běžný ping na <TAILSCALE_IP_SERVER> neprojde (ICMP není povolené), tailscale ping ano (pracuje na úrovni Tailscale, ne OS). PC a notebook spolu nekomunikují; pokud to chcete, přidejte grant autogroup:member → autogroup:self.
Device approval, nebo Tailnet Lock
Podle dokumentace Tailscale nelze mít zapnuté Device approval a Tailnet Lock současně, jde o vzájemně výlučné funkce. Vyberte jednu:
| Funkce | Co chrání | Kdy ji zvolit |
|---|---|---|
| Tailnet Lock | Nový uzel musí podepsat váš důvěryhodný uzel; nevěříte ani koordinačnímu serveru Tailscale. | Doporučeno, pokud máte aspoň 2 desktopová zařízení (Linux/macOS/Windows) jako podepisující uzly. |
| Device approval | Nový uzel musí schválit admin v konzoli. | Když nemáte dva podepisující uzly nebo nechcete spravovat disablement secrets. |
Device approval: admin konzole → Settings → Device management → zapněte ruční schvalování nových zařízení. Nová zařízení pak čekají ve stavu „Needs approval“ (Machines).
Tailnet Lock
Podepisující uzly budou vaše PC a notebook (Tailscale ≥ 1.46.1; Android podepisovat neumí). Server podepisujícím uzlem není: na stroji dostupném z internetu nemají být klíče, které smí do tailnetu přidávat další zařízení.
- Admin konzole → Settings → Device management → Enable Tailnet Lock.
- V sekci Add signing nodes vyberte PC a notebook (minimum jsou dva uzly; třetí, např. záložní stroj, výrazně usnadní obnovu).
- Volitelně zapněte odeslání jednoho disablement secret podpoře Tailscale (záchrana, pokud své ztratíte).
- Zkopírujte vygenerovaný příkaz
tailscale lock init …a spusťte ho na jednom z podepisujících uzlů. - Příkaz vypíše 10 disablement secrets. Uložte je offline (správce hesel, tisk do trezoru); znovu se nezobrazí.
Po init jsou všechny existující uzly včetně serveru podepsané. Ověřte na serveru, že vidí stejné důvěryhodné klíče jako PC:
tailscale lock statusNový nebo přeinstalovaný server se do zamčeného tailnetu dostane až po podpisu z podepisujícího uzlu (příkaz zjistíte na serveru přes tailscale lock status nebo v konzoli u uzlu „Locked out“ → Sign node):
# na PC nebo notebooku
tailscale lock sign nodekey:<NODEKEY_SERVERU>Ztráta zařízení:
- Ztracený, ale nekompromitovaný podepisující uzel odeberte ze zbývajícího:
tailscale lock remove tlpub:<KLIC_ZTRACENEHO>. Uzly, které podepsal, se automaticky přepodepíší. - Kompromitovaný klíč zneplatněte přes
tailscale lock revoke-keys tlpub:<KLIC>s co-signováním dalšími uzly. Potřebujete o jedno co-signování víc, než kolik klíčů revokujete; se dvěma podepisujícími uzly to po kompromitaci jednoho nezvládnete, proto třetí uzel. - Ztráta všech podepisujících uzlů: Tailnet Lock vypněte v konzoli (Device management → Disable Tailnet Lock) jedním disablement secret a inicializujte ho znovu. Bez secretu (a bez kopie u podpory) tailnet obnovit nelze.
MFA a key expiry
Tailscale přihlašování deleguje na identity provider (Google, Microsoft, GitHub, OIDC…). Zapněte na účtu <TAILNET_USER> u IdP vícefaktorové ověření, ideálně passkey nebo hardwarový klíč; kdo ovládne tento účet, může přidat zařízení a upravit policy.
Server má jako tagované zařízení expiraci klíče vypnutou automaticky (ověřte v Machines). Vaše PC a notebook expirují podle nastavení tailnetu (výchozí 180 dní) a čas od času se znovu přihlásí přes IdP, což je žádoucí.
8. Aktualizace
Tailscale aktualizujte jedním mechanismem, ne dvěma: oba používají APT a mohou si navzájem blokovat dpkg zámek. Pro server doporučuji unattended-upgrades, protože běží v okně řízeném systémovým timerem, loguje do /var/log/unattended-upgrades/ a řeší i ostatní balíčky.
Varianta A (doporučená): unattended-upgrades
Instalaci a základní nastavení popisuje článek Unattended upgrades (EN). Pak přidejte repozitář Tailscale mezi povolené originy (klíčové slovo site porovnává hostname repozitáře):
sudo tee /etc/apt/apt.conf.d/52unattended-upgrades-tailscale >/dev/null <<'EOF'
Unattended-Upgrade::Origins-Pattern {
"site=pkgs.tailscale.com";
};
EOFOvěřte, že APT repozitář vidí a unattended-upgrades by Tailscale zahrnul (dry-run nic neinstaluje):
apt-cache policy tailscale
sudo unattended-upgrade --dry-run --debug 2>&1 | grep -i tailscaleVypněte vestavěný auto-update Tailscale, aby se mechanismy nepraly:
sudo tailscale set --auto-update=falseVarianta B: tailscale set --auto-update
Tailscale si aktualizace stahuje sám přes APT podle vlastního plánu (plánování nelze nastavit). Funguje jen se souborem /etc/apt/sources.list.d/tailscale.list ve formátu z kapitoly 3.
sudo tailscale set --auto-update
tailscale get auto-updateCo ověřit po aktualizaci
Upgrade balíčku tailscale restartuje tailscaled, takže SSH relace přes Tailscale na pár sekund spadne; dlouhé práce spouštějte v tmux. Po upgradu zkontrolujte:
tailscale version
tailscale status9. Ověření funkčnosti
Projděte checklist po dokončení konfigurace a znovu po každém rebootu nebo upgradu Tailscale. Se zapnutým Mullvadem doplňte kontroly z doplňku.
Na serveru:
tailscale status # server online, PC/NB v seznamu
tailscale ping <TAILSCALE_IP_PC> # odpověď přes DERP nebo direct
sudo ufw status verbose # deny incoming, SSH port jen na tailscale0 (B: + LAN)
sudo ss -tlnp | grep ':<SSH_PORT> ' # sshd (u socket aktivace vlastník systemd) na 0.0.0.0 a [::]
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication)'Na PC (klient v tailnetu):
ssh -p <SSH_PORT> <ADMIN_USER>@<TAILSCALE_IP_SERVER> # musí projít
nc -vz -w 5 <PUBLIC_IP> <SSH_PORT> # musí skončit timeoutem
tailscale down && nc -vz -w 5 <TAILSCALE_IP_SERVER> <SSH_PORT>; tailscale up # bez Tailscale nedostupnéJen scénář B, z PC v LAN:
ssh -p <SSH_PORT> <ADMIN_USER>@<LAN_IP_SERVER> # záložní cesta musí projítTest po rebootu:
sudo reboot
# z PC po ~1–2 minutách:
ssh -p <SSH_PORT> <ADMIN_USER>@<TAILSCALE_IP_SERVER>Výsledek:
- SSH přes Tailscale funguje z PC i notebooku
- SSH z internetu (
<PUBLIC_IP>) končí timeoutem - (scénář B) SSH z LAN na
<LAN_IP_SERVER>funguje - Heslo se nenabízí, root se nepřihlásí
- Policy testy v admin konzoli prošly
- Po rebootu vše funguje bez ručního zásahu
10. Troubleshooting
Spojení jde přes DERP místo přímého P2P
tailscale status # u peeru „relay "fra"“ místo „direct <ip:port>“
tailscale netcheck # UDP, MappingVariesByDestIP, nejbližší DERP
tailscale ping <TAILSCALE_IP_PC>Ověřte, že netcheck hlásí UDP: true; MappingVariesByDestIP: true znamená obtížný NAT na straně serveru nebo klienta. Při --netfilter-mode=off musí UFW povolovat UDP 41641 (kapitola 6). SSH přes DERP funguje spolehlivě, jen s vyšší latencí. Se zapnutým Mullvadem je relay očekávaný stav (doplněk).
Logy
journalctl -u tailscaled -b --no-pager | tail -50
journalctl -u ssh -b --no-pager | tail -5011. Doplněk: Tailscale současně s Mullvad VPN
Tato kapitola platí jen tehdy, když je na serveru aplikace Mullvad (mullvad-daemon) připojená s kill switchem. Instalaci a nastavení Mullvadu popisuje článek Mullvad VPN na Ubuntu Serveru. Bez výjimky níže SSH přes Tailscale nefunguje.
11.1 Proč Mullvad blokuje Tailscale
Mullvad vytváří tabulku inet mullvad s řetězci input a output (priorita 0, policy drop). Propustí jen provoz přes wg0-mullvad, loopback, spojení na relay Mullvadu a spojení s connection-tracking markem 0x00000f41. Dále přidává ip rule, které vše bez meta marku 0x6d6f6c65 posílají do jeho routovací tabulky (výchozí cesta přes wg0-mullvad). Obě hodnoty platí k 2. 10. 2026: ct mark 0x00000f41 (split tunnel MARK v kódu aplikace) a meta mark 0x6d6f6c65 (fwmark tunelu).
Na hooku input jádro projde base chainy všech tabulek podle priority (UFW v ip filter, Mullvad v inet mullvad) a accept v jedné tabulce znamená jen „pokračuj do další“; drop kdekoli je konečný. Pro SSH přes Tailscale to znamená dva problémy:
- Příchozí SYN z
tailscale0zahodí input chain Mullvadu. Řešení: spojení označitct mark 0x00000f41v řetězci s nižší prioritou (−100), než má Mullvad. - Odpověď sshd nemá žádný mark, takže ji
ip ruleMullvadu pošle dowg0-mullvad, kde ji Mullvad zahodí. Řešení: odpovědím na označená spojení nastavitmeta mark 0x6d6f6c65v řetězci typuroute; jádro pak cestu přepočítá a paket najde v tabulce 52 Tailscale přestailscale0.
11.2 Výjimka z kill switche
Výjimku (tabulka nftables + systemd unit, která ji načte po startu Mullvadu) nastavíte hotovým skriptem: Stakers-space/staking-scripts – mullvad/enable_tailscale. Řešení musí splňovat:
- Příchozí: řetězec
type filter hook inputs prioritou pod 0 (−100) označí jen TCP<SSH_PORT>ztailscale0markemct mark 0x00000f41– nic jiného z tailnetu Mullvadem neprojde. - Odchozí: řetězec
type route hook outputs prioritou mezi −200 a 0 (pod −200 nefunguje a hrozí únik IP tunelu) nastavímeta mark 0x6d6f6c65jen odpovědím na označená spojení (ct direction reply). - Idempotence: opakované načtení pravidla nezdvojí (tabulka se na začátku smaže a založí znovu).
- Unit běží po
mullvad-daemon.serviceatailscaled.service, ale bezRequires=,BindsTo=aPartOf=– restart nebo upgrade Mullvadu výjimku nesmí odstranit. - Žádná DNS výjimka pro
100.100.100.100(server běží s--accept-dns=false) a žádné povolení celého rozsahu100.64.0.0/10mimo tunel – CGNAT používají i poskytovatelé a provoz by obešel kill switch.
Ověření: tabulka výjimky je vedle inet mullvad a při SSH z PC rostou její čítače:
sudo nft list tables
sudo nft list ruleset | grep -B2 -A2 0x00000f4111.3 Pořadí ip rule: Mullvad musí být před Tailscale
Tailscale přidává pravidla s pevnými prioritami 5210–5270. Mullvad přidává svá pravidla při každém připojení bez explicitní priority, takže je jádro umístí před první existující pravidlo. Pokud se Mullvad připojí dřív než tailscaled, jeho pravidla skončí na 32764/32765 (za Tailscale), provoz tailscaled jde přímo na eth0, Mullvad ho zahodí a Tailscale je offline. Správný stav (pravidla Mullvadu 5208/5209 před 5210):
0: from all lookup local
5208: from all lookup main suppress_prefixlength 0
5209: not from all fwmark 0x6d6f6c65 lookup 1836018789
5210: from all fwmark 0x80000/0xff0000 lookup main
...
5270: from all lookup 52Okamžitá oprava je mullvad reconnect. Aby tailscaled při bootu startoval před Mullvadem, přidejte drop-in (sudo systemctl edit mullvad-daemon.service):
[Unit]
After=tailscaled.serviceMechanismus je odvozený ze zdrojového kódu Mullvadu a chování jádra; ověřte ho na svém stroji po rebootu (ip rule show).
11.4 Scénář B: SSH z LAN se zapnutým Mullvadem
Kill switch Mullvadu zahazuje i provoz z lokální sítě, takže záložní SSH z LAN (scénář B) se zapnutým Mullvadem nefunguje. Povolte LAN v Mullvadu:
mullvad lan set allow
mullvad lan getMullvad pak propustí provoz z a do privátních rozsahů; které porty jsou z LAN dostupné, dál určuje UFW. Odpovědi do LAN jdou přes eth0 díky pravidlu 5208 (lookup main suppress_prefixlength 0). Ve scénáři A LAN v Mullvadu nepovolujte.
11.5 Aktualizace a ověření
Pokud máte Mullvad z jeho APT repozitáře a používáte unattended-upgrades, přidejte do Origins-Pattern z kapitoly 8 i jeho hostname (zjistíte z apt-cache policy mullvad-vpn). Upgrade mullvad-vpn restartuje daemon, který znovu vytvoří inet mullvad a svá ip rule; tabulka výjimky má zůstat. Po upgradu a po rebootu ověřte:
mullvad status # Connected
sudo nft list tables # inet mullvad + tabulka výjimky
ip rule show # 5208/5209 před 5210 (kapitola 11.3)
curl https://am.i.mullvad.net/connected # provoz serveru jde přes Mullvad11.6 DERP místo P2P
S Mullvadem je relay očekávaný stav: tailscaled posílá svůj UDP provoz tunelem Mullvadu, peer vidí jako zdroj exit IP Mullvadu a Mullvad nenabízí přesměrování portů, takže hole punching obvykle selže. Spojení „opravovat“ výjimkou pro UDP 41641 mimo tunel nedoporučuji: odhalili byste peerům skutečnou IP serveru.
11.7 Alternativa: Mullvad exit nodes přes Tailscale
Místo aplikace Mullvad na serveru lze použít Mullvad VPN add-on v Tailscale: server pošle veškerý internetový provoz přes Mullvad server, který se v tailnetu tváří jako exit node. Odpadne výjimka z kill switche i hlídání pořadí ip rule, protože na serveru běží jen jeden VPN klient. Funkce je k 2. 10. 2026 v betě (Tailscale ≥ 1.48.2).
Dává smysl, když server neposkytuje žádné veřejné služby na své veřejné IP (odpovědi by odcházely přes Mullvad), chcete jednodušší správu a nepotřebujete funkce aplikace Mullvad, které add-on nenabízí (vlastní kill switch, nastavení aplikace na serveru).
Policy z kapitoly 7 rozšíříte o přidělení licence přes nodeAttrs a grant na autogroup:internet. Server tím smí iniciovat spojení do internetu přes exit node, do tailnetu stále nesmí nikam:
// Licence Mullvad add-onu pro server.
"nodeAttrs": [
{
"target": ["tag:server"],
"attr": ["mullvad"],
},
],
// do "grants" přidejte:
{
// Server smí používat exit node (internet), ne zařízení v tailnetu.
"src": ["tag:server"],
"dst": ["autogroup:internet"],
"ip": ["*"],
},Licence spravujte buď v admin konzoli (Settings → General → Mullvad VPN → Configure), nebo přes nodeAttrs v policy, ne oběma způsoby současně. Základní add-on obsahuje 5 licencí.
Nejdřív vypněte výjimku a aplikaci Mullvad (odinstalaci popisuje článek Mullvad VPN › Odstranění), pak vyberte exit node (seznam se po prvním přidělení licence může načítat až 2 minuty):
mullvad lockdown-mode set off
mullvad disconnect
tailscale exit-node list --filter=<ZEME>
sudo tailscale set --exit-node=<MULLVAD_EXIT_NODE>
curl https://am.i.mullvad.net/connectedVe scénáři B nebo když server potřebuje přístup do vlastní LAN přidejte --exit-node-allow-lan-access, jinak by odpovědi do LAN odcházely přes exit node. DNS: s --accept-dns=false server používá svůj lokální resolver a dotazy odcházejí přes exit node; pro jistotu proti DNS leakům nastavte jako resolver Mullvad DNS nebo přepněte na --accept-dns=true s globálním nameserverem v admin konzoli. S Tailnet Lock musíte každý Mullvad exit node podepsat, a to ze zařízení, které má samo licenci Mullvad.
| Oblast | Aplikace Mullvad na serveru | Mullvad exit node přes Tailscale |
|---|---|---|
| Kill switch | Vlastní firewall Mullvadu, volitelně i když daemon neběží (lockdown mode). | Nezávislý kill switch není; po tailscale down nebo pádu tailscaled jde provoz přímo s veřejnou IP. |
| Nezávislost | VPN funguje i při výpadku nebo zrušení Tailscale. | VPN i SSH přístup závisí na jednom klientovi a jednom účtu. |
| Anonymita vůči Tailscale | Tailscale o Mullvad účtu neví. | Mullvad účty spravuje Tailscale a ví, který uživatel k nim patří; z logů může vidět, ke kterému Mullvad serveru se zařízení připojuje. |
| Veřejné služby serveru | Fungují podle nastavení split tunnelu. | Odpovědi odcházejí přes exit node, veřejné služby na IP serveru prakticky nejdou. |
| Složitost | Výjimka z kill switche, hlídání pořadí ip rule. | Jen policy a tailscale set --exit-node. |
12. Zdroje
Oficiální dokumentace a zdroje ověřené k 2. 10. 2026.
Související návody na Vrealmatic
- Instalace, zabezpečení a správa Ubuntu Serveru – změna SSH portu, UFW
- SSH klíče – přihlášení klíčem, konfigurace sshd
- 2FA přes Google Authenticator
- Unattended upgrades (EN)
- Mullvad VPN na Ubuntu Serveru
Tailscale
- Tailscale Packages – stable track – APT repozitář, klíče
noarmor.gpg,.listpro noble/resolute, aktuální verze - tailscale up – flagy
--accept-dns,--accept-routes,--advertise-tags,--netfilter-mode - Tailscale CLI –
tailscale set(--auto-update,--netfilter-mode,--exit-node),status,netcheck,ping,lock - Grants syntax –
src/dst/ip, deny-by-default,autogroup:internet - Group devices with tags –
tagOwners, key expiry tagovaných zařízení, změna tagů - Tailnet Lock – init, podepisování, disablement secrets, vzájemná výlučnost s Device approval
- Use ufw to lock down an Ubuntu server – UFW na
tailscale0, MFA na identity provideru - Mullvad exit nodes – add-on, licence,
nodeAttrs, podepisování při Tailnet Lock - tailscale/tailscale – issue #14900 – výpis řetězce
ts-inputsiifname "tailscale0" accept
Mullvad
- Split tunneling with Linux (advanced) –
ct mark 0x00000f41,meta mark 0x6d6f6c65, priority řetězců, příklad pro příchozí provoz - mullvad/mullvadvpn-app – zdrojový kód:
talpid-core/src/firewall/linux.rs(řetězce a priority tabulkyinet mullvad),talpid-routing/src/unix/linux.rs(ip rulebez explicitní priority) - Stakers-space/staking-scripts – mullvad/enable_tailscale – výjimka z kill switche pro Tailscale

Potřebujete bezpečně nastavit server?
Navrhneme, zabezpečíme a zdokumentujeme sítě i servery.