
네트워크 인식 SSH 라우터 - 활성 VPN 또는 네트워크에 따라 다른 IP/포트/키/점프 호스트로 연결을 라우팅합니다.
| CI | 코드 | OpenSpec | 보안 |
|---|---|---|---|
|
|
|
|
|
네트워크 인식 SSH 라우터. 현재 활성 네트워크나 VPN을 감지하여 각 SSH 연결에 대해 적절한 호스트, 포트, 아이덴티티 파일, 점프 호스트를 ~/.ssh/config를 건드리지 않고 자동으로 선택합니다.
각 논리적 호스트를 default 프로필과 네트워크별 선택적 오버라이드로 한 번 정의합니다. 각 연결 시 sshroute는 현재 어떤 네트워크( VPN, 사무실 LAN, WireGuard 피어 등)에 있는지 감지하고, 올바른 SSH 매개변수를 확인한 후 실제 /usr/bin/ssh로 넘깁니다.
ssh myserver
→ sshroute 감지: corp-vpn 활성
→ 확인: 10.100.0.50:2222 via bastion.corp.internal
→ exec /usr/bin/ssh -p 2222 -i ~/.ssh/corp_key -J bastion.corp.internal 10.100.0.50
랩에는 적어도 두 가지 현실이 있을 겁니다: 집에서 LAN에 있거나, 외출 중에 WireGuard나 다른 VPN을 통해 접속하는 경우입니다. 문제는 ~/.ssh/config가 현재 어떤 상태인지 모른다는 점입니다. 그래서 별칭을 따로 만들거나(server-lan, server-vpn), 절반만 작동하는 점프 호스트를 사용하거나, IP를 외우게 됩니다.
sshroute는 각 연결 전에 현재 네트워크를 감지하여 이 문제를 해결합니다. WireGuard 인터페이스가 작동 중이고 피어 라우트가 존재하면 터널 IP로 직접 연결합니다. LAN에 있을 때는 로컬 주소를 사용합니다. 둘 다 도달할 수 없으면 공용 호스트명으로 대체됩니다. 하나의 별칭, 세 가지 현실, 수동 전환 불필요.
또한 SSH를 투명하게 가로챕니다. git push, rsync, scp 모두 섀도우 모드 설정 후 자동으로 이를 통해 작동합니다. 래퍼나 셸 함수, 고민이 필요 없습니다.
기업 네트워크는 더 복잡합니다. 공용 인터넷, 사이트 간 VPN, 개인 VPN 분할 터널(분할 터널링) 등이 있을 수 있으며, 그 안에서 타겟 환경(dev, staging, prod)마다 다른 점프 호스트와 키를 사용합니다. 이것을 ~/.ssh/config에 정리하려면 거대한 설정 파일 하나를 유지하거나, 팀원마다 다르게 관리하는 스크립트를 작성해야 합니다.
sshroute를 사용하면 라우팅 로직을 선언적으로 정의하고, 버전 관리되는 YAML 파일에 저장하며, 팀 전체에 공유할 수 있습니다. 동일한 설정이 모든 사람에게 적용됩니다. 각 머신에서 활성화된 인터페이스나 라우트를 기반으로 올바른 네트워크가 자동으로 감지됩니다. 키, 포트, 사용자, 점프 호스트가 사용자가 신경 쓸 필요 없이 확인됩니다.
| 기능 | ~/.ssh/config | WireGuard 전용 | Teleport / Boundary | sshroute |
|---|---|---|---|---|
| 현재 네트워크 감지 | ❌ | ❌ | ❌ | ✅ |
| 최적 경로 자동 선택 | ❌ | ❌ | ❌ | ✅ |
| 연결 실패 시 대체(fallback) | ❌ | ❌ | ✅ | ✅ |
| 연결 끊김 시 자동 재연결 + 경로 변경 | ❌ | ⚠️ 터널 로밍 | ⚠️ 고정 프록시 경유 | ✅ |
| 어느 위치에서든 호스트당 하나의 명령 | ❌ | ⚠️ VPN 켜야 함 | ✅ | ✅ |
| 10개 호스트 × 4개 경로의 설정 크기 | 📄 ~600줄 | 📄 ~600줄 + VPN 설정 | 📄 서버 측 설정 | 📄 ~60줄 |
| 모바일 기기 로밍 | ⚠️ 수동 별칭 | ⚠️ VPN 필요 | ✅ | ✅ |
| 점프 호스트 자동 체이닝 | ⚠️ 수동 -J | ➖ 해당 없음 | ✅ | ✅ |
| scp / rsync / git / Ansible 호환 | ✅ | ✅ | ⚠️ 일부 | ✅ |
| 타겟에 서버 측 설치 불필요 | ✅ | ❌ | ❌ | ✅ |
| 인증 서버나 데몬 실행 불필요 | ✅ | ❌ | ❌ | ✅ |
| 클라이언트 에이전트 불필요 | ✅ | ❌ | ❌ | ✅ |
| 오픈 소스, 완전 자체 호스팅 | ✅ | ✅ | ⚠️ 오픈코어 | ✅ |
Teleport와 Boundary는 라우팅 위에 액세스 제어, 감사 로그, 인증서 기반 인증을 추가하는 별도의 범주입니다. 그런 기능이 필요하면 사용하세요. sshroute는 중앙 인증 서버 운영의 부담 없이 라우팅 지능만 필요한 경우를 위한 것입니다.
GitHub Releases에서 최신 릴리스를 다운로드합니다. Linux, macOS, Android용 AMD64 및 ARM64 바이너리가 제공됩니다.
go install github.com/thereisnotime/sshroute@latest
GitHub Releases에서 android_arm64 tarball을 다운로드하고, 압축을 풀어 ~/.local/bin에 바이너리를 배치합니다:
mkdir -p ~/.local/bin
curl -Lo "$TMPDIR/sshroute.tar.gz" \
https://github.com/thereisnotime/sshroute/releases/latest/download/sshroute_android_arm64.tar.gz
tar -xzf "$TMPDIR/sshroute.tar.gz" -C ~/.local/bin sshroute
chmod +x ~/.local/bin/sshroute
~/.bashrc나 ~/.profile에 ~/.local/bin을 PATH에 추가합니다(아직 없다면):
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
또는 Termux의 Go를 사용하여 소스에서 컴파일합니다. 공식 Go 툴체인이 android/arm64 바이너리를 제공하지 않으므로, GOTOOLCHAIN=local로 설정하여 Termux가 제공하는 Go를 사용합니다:
GOTOOLCHAIN=local go install github.com/thereisnotime/sshroute@latest
설치 후, Termux에는 /usr/bin/ssh가 없으므로 SSH 바이너리 경로를 설정합니다:
# ~/.config/sshroute/config.yaml
ssh_binary: /data/data/com.termux/files/usr/bin/ssh
또는 환경 변수로 설정: export SSHROUTE_SSH=$(which ssh)
docker run --rm -v ~/.config/sshroute:/root/.config/sshroute \
ghcr.io/thereisnotime/sshroute network
podman run --rm -v ~/.config/sshroute:/root/.config/sshroute \
ghcr.io/thereisnotime/sshroute network
SELinux 활성 시스템(Fedora, RHEL 등)에서는 볼륨 플래그에 :Z를 추가합니다:
podman run --rm -v ~/.config/sshroute:/root/.config/sshroute:Z \
ghcr.io/thereisnotime/sshroute network
$PATH에서 더 앞쪽에 ssh로 sshroute를 설치합니다. 터미널, git, rsync, scp의 모든 SSH 호출이 자동으로 가로채집니다. 설정에 없는 호스트는 변경 없이 /usr/bin/ssh로 전달됩니다.
mkdir -p ~/.local/bin
ln -s $(which sshroute) ~/.local/bin/ssh
# ~/.bashrc 또는 ~/.zshrc에 추가 (아직 없다면):
export PATH="$HOME/.local/bin:$PATH"
# 기본 프로필로 호스트 추가
sshroute add myserver --host myserver.example.com --user alice --key ~/.ssh/id_ed25519
# VPN 전용 오버라이드 추가
sshroute add myserver --network vpn --host 10.8.0.50 --port 2222 --jump bastion.vpn
# 연결 — 네트워크가 자동으로 감지됨
sshroute connect myserver
# 실행하지 않고 확인된 명령 미리 보기
sshroute connect myserver --dry-run
# 현재 활성 네트워크 보기
sshroute network
이 플래그들은 모든 명령에 적용됩니다: