sish: Ngrok na vlastním železe
Představení projektu sish jako alternativy k ngroku pro bezpečné tunelování na vlastním serveru s vlastní doménou.
Nejsem nijak spojen s projektem
sish. Jen mi přijde jako skvělé řešení pro bezpečné tunelování a chtěl jsem se o něj podělit. Už ho nějakou dobu používám a jsem s ním velmi spokojený. Je to skvělá alternativa kngroku, která nabízí plnou kontrolu nad vašimi daty a provozem.
sish Představení
sish je open-source projekt, který vytvořil Antonio Mika. Umožňuje vývojářům bezpečně vystavit svoje lokální prostředí do internetu bez nutnosti úpravy Firewallu, podobně jako ngrok, ale bez nutnosti mít nainstalovaného lokálního klienta, jelikož využívá standardní SSH protokol pro vytváření tunelů.
V moment, kdy vývojáři potřebují sdílet rozpracované změny s kolegy nebo zákazníky, tak narazí na ngrok jelikož je to první výsledek, který se objeví ve vyhledávačích. Nicméně ngrok je proprietární řešení, skrze které potečou vaše potenciálně citlivá data. Bezplatná verze má omezení, která nemusí vyhovovat všem případům použití.
Nejětší problém, který s ngrokem mám, je ten, že veškerý provoz je směrován přes jejich servery, přičemž TLS terminace se děje na jejich infrastruktuře, což představuje riziko nešifrovaného provozu mezi ngrok servery a lokálními službami. To může být významný bezpečnostní problém. Minimálně je to riziko, který by se měl brát v úvahu v rámci Risk Assessmentu.
V poslední době vzniklo dost alternativ k ngroku, které jsou open-source, ale nepřijdou mi tak flexibilní a jednoduché jako sish. Většina z nich vyžaduje instalaci klientského software na vývojářských strojích, což může být překážkou pro adopci, nebo nejsou snadno self-hostovatelné. sish vyniká tím, že využívá standardní SSH protokol. Už i Windows ve výchozí instalaci obsahuje ssh klienta, což usnadňuje použití SSH protokolu bez nutnosti dalšího softwaru.
Pokud můžete tolerovat občasné výpadky (kvůli údržbě), můžete mít plně funkční tunelovací řešení za minimální náklady a s maximální kontrolou nad daty. Obvykle můžete použít nejlevnější VM na jakémkoli cloudovém poskytovateli.
Pro více informací o tom, jak sish funguje, se podívejte do oficiální dokumentace: https://docs.ssi.sh/how-it-works
Použití
Abyste měli představu o tom, jak sish funguje v praxi a jestli vyhovuje vašim potřebám, tak vám ho ukážu na jednoduchém příkladu. Pro pokročilejší funkce se můžete podívat do oficiálního cheatsheetu: https://docs.ssi.sh/cheatsheet
Pro demonstraci použiju sish server, který jsem vytvořil jako součást tohoto tutoriálu.
Lokální službu můžu vystavit pomocí tohoto příkazu:
| |
Výstup bude vypadat nějak takto:
| |
Pokud zmiňovanou URL otevřeme v prohlížeči, měli bychom vidět službu běžící na našem lokálním počítači, ale přístupnou přes sish tunel a zabezpečenou certifikátem.

Subdoména nemusí být specifickovaná. Pokud se nezadá, sish použije náhodnou hodnotu:
| |
Ke zjednodušení používání, můžete vytvořit vlastní alias ve vašem zsh/bash rc souboru:
| |
Díky této funkci lze spustit tunel jednoduše takto:
| |
Pokud se funkce bude jmenovat ngrok, tak můžete použít stejný příkaz jako předtím, ale bude používat váš self-hosted sish server místo ngrok.
Nasazení
Pro toto demo použiju nejlevnější VM v Azuru s manuálně vyžádaným wildcard certifikátem skrze Let’s Encrypt. Lze použít jakýkoliv cloud nebo vlastní železo.
Kdykoli uvidíte
dt.smtl.cz, nahraďte jej vlastní doménou.
Krok 1: Příprava VM
Na internetu už je spousta návodů, jak vytvořit novou VM a nainstalovat na ni Docker, takže nevidím důvod, proč to rozepisovat do detailu. Postupujte podle svých osvědčených postupů nebo návodu na internetu a vytvote novou Ubuntu VM a nainstalujte Dockerem a Docker Compose.
Jakmile bude VM připravená, povolte následující porty ve firewallu VM:
22- Obvyklý SSH port pro správu VM- Měl by být omezen pouze na vaše IP adresy nebo VPN, aby se zabránilo neautorizovanému přístupu
2222-sishSSH port pro správu tunelů- Měl by být omezen pouze pro IP adresy vývojářů nebo VPN, aby se zabránilo zneužití
80- HTTP port pro normální HTTP komunikaci- Měl by být dostupný veřejně
443- HTTPS port pro zabezpečenou HTTPs komunikaci- Měl by být dostupný veřejně
Krok 2: Nastavení domény
Nastavení se bude lišit v závislosti na vašem poskytovateli DNS. Je potřeba vytvořit dva DNS záznamy:
- Záznam typu
A- Název:
dt.smtl.cz - Hodnota:
<Public_IP_Of_VM>
- Název:
- Záznam typu
CNAME- Název:
*.dt.smtl.cz - Hodnota:
dt.smtl.cz
- Název:
Konfigurace DNS záznamůKrok 3: Získání wildcard certifikátu
Používám WEDOS jako svého DNS poskytovatele, tak použiju DNS-01 challenge pro získání certifikátu. Zjistěte si, jaké možnosti pro DNS-01 challenge nabízí váš DNS poskytovatel.
K získání certifikátu použiju lego klienta v Docker kontejneru.
Potřebné lego parametry pro všechny DNS poskytovatele najdete zde: https://go-acme.github.io/lego/dns/index.html
| |
Výsledek by měl vypadat takto:

Krok 4: Vytvoření potřebných konfigurací
Jakmile je certifikát připraven, můžeme přejít k dalšímu kroku a vytvořit potřebné konfigurační soubory a složky.
Představenou strukturu nemusíte dodržovat. Pokud vám nevyhovuje, tak si ji můžete upravit podle svých představ, ale ujistěte se, že aktualizujete cesty v konfiguračních souborech odpovídajícím způsobem.
Připojte se k VM a vytvořte následující strukturu adresářů:
mkdir -p /srv/sish/{certs,keys,pubkeys,ssh-keys}
| |
| |
| |
Zkopírujte získaný certifikát a privátní klíč do certs adresáře.
| |
Do složky pubkeys přidejte veřejné klíče všech uživatelů, kteří budou mít přístup k vytváření tunelů. Každý klíč by měl být v samostatném souboru s .pub příponou.
Krok 5: Spuštění serveru
Ve složce /srv/sish spusťte docker compose up -d. Ověřte, že server běží bez chyb: docker logs -f sish
docker compose logs -fK ověření že server běží a naslouchá na správných portech, můžete použít netcat:
| |
Ten samý test můžete provést z vašeho lokálního počítače, abyste ověřili, že porty jsou otevřené a přístupné z vaší lokace:
| |
Krok 6: Ověření funkčnosti
Abychom otestovali, že tunelování funguje správně, vytvoříme jednoduchý tunel pro službu whoami, která běží lokálně na vašem počítači. Tato služba vrátí detaily požadavku, takže můžeme ověřit, že provoz je správně směrován skrze tunel.
- Spusťte kontejner
whoami:docker run -d -p 9090:80 --name iamfoo traefik/whoami
- Otevřete prohlížeč a navštivte
http://localhost:9090,whoamistránka by měla být zobrazena. - Vytvořte tunel pomocí:
- Otevřete zobrazenou URL v prohlížeči:
https://whoami-test-jc.dt.smtl.cz
Pokud něco nefunguje, tak zkontrolujte sish logy pomocí docker logs -f sish, jestli se neobjevují nějaké chyby nebo varování.
Závěr
Úspěšně jste nakonfigurovali self-hosted alternativu k ngrok pomocí sish. Nyní můžete vytvářet tunely k vašim lokálním službám a přistupovat k nim bezpečně přes internet. Nezapomeňte monitorovat server a udržovat jej aktuální, aby byla zajištěna bezpečnost a stabilita.
Podívejte se na kompletní příklad konfiguračního souboru a přizpůsobte jej svým potřebám.
✨ Bonus: Autentizace pomocí OS uživatelů (smallstep SSH certifikáty)
Jelikož sish je dostupný skrze SSH protokol, lze k jeho zabezpečení použít různé metody (Bastion/Jump servery, VPN, Firewall, Krátkodobé ssh klíče, …)
Pokud už máte existující autentizační systém pro připojování k Ubuntu VM, můžete jej využít pro autentizaci k sish serveru. Tím pádem nemusíte spravovat samostatné klíče pro sish v lokálním adresáři (/pubkeys).
Abyste mohli využít autentizaci na úrovni OS, udělejte následující:
- Použijte možnost
authentication: falsevsishkonfiguračním souboru - Upravte
compose.ymla vystavtesishslužbu pouze na localhostu:
1 2ports: - "127.0.0.1:2222:2222"
Tímto způsobem nebude interní SSH port sish server dostupný zvenčí.
Aby bylo možné vytvořit tunely, je potřeba se nejdříve připojit k Docker host systému a poté se připojit k sish serveru skrze localhost.
Již zmíněný příkaz pro vytvoření tunelu by se změnil v toto:
| |
Tento příkaz se nejdříve připojí k Docker host systému (dt.smtl.cz) pomocí OS uživatele ansible, a poté se připojí k sish službě běžící na localhostu přes port 2222. Tímto způsobem můžete využít svůj stávající autentizační systém založený na OS uživatelích, aniž byste museli spravovat samostatné klíče pro sish.
SSH připojení skrze proxyKe zjednodušení můžete použít následující SSH konfiguraci:
| |
Díky této konfiguraci se příkaz zjednoduší na:
ssh -R whoami-test-jc:80:localhost:9090 dt
Připojení skrze SSH aliasu✨ Bonus 2: Automatické obnovování certifikátu
Manuálně generovat certifikát a kopírovat ho do sish serveru je v pořádku pro testování, ale není to udržitelné řešení pro produkční prostředí. Certifikáty Let’s Encrypt jsou platné pouze 90 dní (brzy 45 dní), takže je potřeba mít nastavený proces pro jejich pravidelné obnovování.
Hlavním cílem je mít cron job, který bude pravidelně spouštět příkaz pro obnovu certifikátu a aktualizovat certifikáty v certs adresáři.
Jelikož je potřeba restartovat sish kontejner po obnově certifikátu, je jednodušší mít lego přístupný na Docker hostu a vytvořit skript, který bude řešit obnovu a restartování kontejneru.
Nejprve nainstalujte lego na Docker hostu.
Pro demo preferuji získání binárky z Docker image, ale měli byste dodržovat otestované postupy pro instalaci (a udržování aktuálnosti) softwaru na vašich serverech.
docker run --rm -ti -v "${PWD}:/data" -w /data --entrypoint sh goacme/lego -c 'cp /lego /data/lego'
Tento příkaz zkopíruje lego binárku do aktuálního adresáře, takže ji můžete přesunout na více standardní místo.
mv ./lego /usr/local/bin/lego
Skript, který obnový certifikát, by mohl vypadat nějak takto:
| |
Kopírovaní certifikátu a restartování kontejneru je definovaný v následujícím skriptu:
| |
Nastavte oba skripty jako spustitelné: chmod +x /srv/sish/hooks/*.sh
Nakonec vytvořte cron job, který bude pravidelně spouštět skript pro obnovu certifikátu.
Vždy vyberte náhodnou hodinu a minutu pro spuštění obnovy, aby nedošlo k přetížení ACME serverů. Více informací naleznete na https://go-acme.github.io/lego/usage/cli/renew-a-certificate/index.html#automatic-renewal.
29 2 * * * /srv/sish/hooks/renew-cert.sh >> /srv/sish/renew.log 2>&1


