SSHPiper on Incus
SSH 리버스 프록시 서버로, 사용자 이름 기반 라우팅을 통해 여러 백엔드 서버에 SSH 접속을 중계합니다.
개요
| 항목 | 값 |
|---|---|
| 컨테이너 이름 | sshpiper |
| 호스트 OS | Debian 12 (bookworm) |
| SSHPiper 버전 | 1.5.1 |
| 리스닝 포트 | 2222 |
| IP 주소 | 10.253.100.34 |
| 플러그인 | yaml |
아키텍처
클라이언트 → [호스트:2222] → [sshpiper 컨테이너:2222] → 백엔드 서버:22
proxy device sshpiperd
접속 방법
# 형식: ssh -p 2222 <alias>@<호스트>
ssh -p 2222 baserow@localhost
ssh -p 2222 caddy@localhost
ssh -p 2222 k8s@localhost
등록된 파이프
| Alias | 백엔드 서버 | 대상 사용자 |
|---|---|---|
baserow |
10.253.103.104 | root |
caddy |
10.253.103.139 | root |
crowdsec |
10.253.100.240 | root |
hey |
10.253.103.80 | root |
k8s |
10.253.103.124 | root |
log-collector, log |
10.253.100.55 | root |
tor, tor-server |
10.253.101.178 | root |
vaultwarden, vault |
10.253.100.48 | root |
Alias와 실제 접속 사용자
현재 설정에서는 모든 파이프가 to.username: root로 되어 있어서, 어떤 alias로 접속하든 백엔드 서버에는 root로 접속합니다.
ssh -p 2222 baserow@host → root@10.253.103.104
ssh -p 2222 caddy@host → root@10.253.103.139
ssh -p 2222 k8s@host → root@10.253.103.124
from.username: sshpiper에 접속할 때 사용하는 라우팅용 aliasto.username: 실제 백엔드 서버에 접속하는 계정
다른 사용자로 접속하려면
# 예: deploy 사용자로 접속
- from:
- username: "baserow"
to:
host: 10.253.103.104:22
username: deploy # root 대신 다른 계정
ignore_hostkey: true
# 또는 원래 입력한 사용자 이름 유지 (username 생략)
- from:
- username_regex: ".*" # 모든 사용자
to:
host: 10.253.103.104:22
# username 생략 → 클라이언트가 입력한 사용자명 그대로 사용
ignore_hostkey: true
SSH 키 인증
SSHPiper는 비밀번호 인증 외에 SSH 키 인증도 지원합니다.
인증 방향
클라이언트 ──[①]──→ sshpiper ──[②]──→ 백엔드 서버
from.authorized_keys to.private_key
| 방향 | 설정 | 설명 |
|---|---|---|
| ① 클라이언트 → sshpiper | from.authorized_keys |
클라이언트 공개키 검증 |
| ② sshpiper → 백엔드 | to.private_key |
백엔드 접속용 개인키 |
백엔드 키 인증 설정 (sshpiper → 백엔드)
클라이언트는 비밀번호로 접속하고, sshpiper가 백엔드에는 키로 접속하는 방식입니다.
1. sshpiper에서 키 생성
incus exec sshpiper -- ssh-keygen -t ed25519 -f /etc/sshpiper/id_backend -N ''
2. 백엔드 서버에 공개키 등록
# 공개키 확인
incus exec sshpiper -- cat /etc/sshpiper/id_backend.pub
# 백엔드 서버의 authorized_keys에 추가
incus exec <백엔드> -- bash -c 'echo "<공개키내용>" >> /root/.ssh/authorized_keys'
3. pipes.yaml 설정
- from:
- username: "myserver"
to:
host: 10.x.x.x:22
username: root
private_key: /etc/sshpiper/id_backend # 백엔드 접속용 개인키
ignore_hostkey: true
클라이언트 키 인증 설정 (클라이언트 → sshpiper)
특정 클라이언트 공개키만 허용하는 방식입니다.
1. 허용할 공개키 파일 생성
# 클라이언트의 공개키를 sshpiper에 등록
incus exec sshpiper -- bash -c 'cat > /etc/sshpiper/authorized_keys_myserver << EOF
ssh-ed25519 AAAA... user@client
EOF'
2. pipes.yaml 설정
- from:
- username: "myserver"
authorized_keys:
- /etc/sshpiper/authorized_keys_myserver # 허용할 클라이언트 공개키
to:
host: 10.x.x.x:22
username: root
private_key: /etc/sshpiper/id_backend
ignore_hostkey: true
양방향 키 인증 (가장 안전)
클라이언트도 키로, 백엔드도 키로 접속하는 방식입니다.
- from:
- username: "secure-server"
authorized_keys:
- /etc/sshpiper/authorized_keys_secure # 클라이언트 공개키
to:
host: 10.x.x.x:22
username: root
private_key: /etc/sshpiper/id_secure # 백엔드용 개인키
ignore_hostkey: true
인라인 키 데이터
파일 경로 대신 base64 인코딩된 키를 직접 설정할 수도 있습니다.
- from:
- username: "inline-example"
authorized_keys_data:
- "c3NoLWVkMjU1MTkgQUFBQS4uLg==" # base64 인코딩된 공개키
to:
host: 10.x.x.x:22
username: root
private_key_data: "LS0tLS1CRUdJTi4uLg==" # base64 인코딩된 개인키
ignore_hostkey: true
설정 파일
파이프 설정 (/etc/sshpiper/pipes.yaml)
version: "1.0"
pipes:
- from:
- username: "서버별칭"
to:
host: 10.x.x.x:22
username: root
ignore_hostkey: true
Systemd 서비스 (/etc/systemd/system/sshpiper.service)
[Unit]
Description=SSHPiper - SSH Reverse Proxy
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/sshpiperd -l 0.0.0.0 -p 2222 -i /etc/sshpiper/host_key /usr/local/bin/plugins/yaml --config /etc/sshpiper/pipes.yaml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
관리 명령어
# 서비스 상태 확인
incus exec sshpiper -- systemctl status sshpiper
# 서비스 재시작
incus exec sshpiper -- systemctl restart sshpiper
# 로그 확인
incus exec sshpiper -- journalctl -u sshpiper -f
# 설정 파일 편집
incus exec sshpiper -- nano /etc/sshpiper/pipes.yaml
새 서버 추가
pipes.yaml에 새 파이프 추가:
- from:
- username: "새서버"
to:
host: 10.x.x.x:22
username: root
ignore_hostkey: true
- 서비스 재시작:
incus exec sshpiper -- systemctl restart sshpiper
사용 가능한 플러그인
| 플러그인 | 설명 |
|---|---|
yaml |
YAML 파일 기반 라우팅 (현재 사용 중) |
docker |
Docker 컨테이너 라우팅 |
kubernetes |
Kubernetes Pod 라우팅 |
workingdir |
작업 디렉토리 기반 라우팅 |
fixed |
고정 대상 라우팅 |
failtoban |
실패 시 차단 기능 |
username-router |
사용자 이름 기반 라우팅 |
Incus 프록시 설정
컨테이너에 proxy2222 디바이스가 설정되어 호스트의 2222 포트가 컨테이너의 2222 포트로 포워딩됩니다.
# 프록시 설정 확인
incus config device show sshpiper
# 프록시 추가 (이미 설정됨)
incus config device add sshpiper proxy2222 proxy listen=tcp:0.0.0.0:2222 connect=tcp:127.0.0.1:2222
트러블슈팅
접속 불가 시
# 서비스 상태 확인
incus exec sshpiper -- systemctl status sshpiper
# 포트 리스닝 확인
incus exec sshpiper -- ss -tlnp | grep 2222
# 프로세스 확인
incus exec sshpiper -- ps aux | grep sshpiper
로그 확인
# 실시간 로그
incus exec sshpiper -- journalctl -u sshpiper -f
# 최근 에러
incus exec sshpiper -- journalctl -u sshpiper -p err --since "1 hour ago"