docs: SSHPiper on Incus 설치 및 설정 문서

- 개요 및 아키텍처
- 등록된 파이프 목록
- Alias와 실제 접속 사용자 설명
- SSH 키 인증 설정 (백엔드/클라이언트/양방향)
- 관리 명령어 및 트러블슈팅

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-17 01:09:00 +09:00
commit bcda29fd26

297
README.md Normal file
View File

@@ -0,0 +1,297 @@
# 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
```
## 접속 방법
```bash
# 형식: 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에 접속할 때 사용하는 **라우팅용 alias**
- `to.username`: 실제 백엔드 서버에 접속하는 **계정**
### 다른 사용자로 접속하려면
```yaml
# 예: 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에서 키 생성**
```bash
incus exec sshpiper -- ssh-keygen -t ed25519 -f /etc/sshpiper/id_backend -N ''
```
**2. 백엔드 서버에 공개키 등록**
```bash
# 공개키 확인
incus exec sshpiper -- cat /etc/sshpiper/id_backend.pub
# 백엔드 서버의 authorized_keys에 추가
incus exec <백엔드> -- bash -c 'echo "<공개키내용>" >> /root/.ssh/authorized_keys'
```
**3. pipes.yaml 설정**
```yaml
- from:
- username: "myserver"
to:
host: 10.x.x.x:22
username: root
private_key: /etc/sshpiper/id_backend # 백엔드 접속용 개인키
ignore_hostkey: true
```
### 클라이언트 키 인증 설정 (클라이언트 → sshpiper)
특정 클라이언트 공개키만 허용하는 방식입니다.
**1. 허용할 공개키 파일 생성**
```bash
# 클라이언트의 공개키를 sshpiper에 등록
incus exec sshpiper -- bash -c 'cat > /etc/sshpiper/authorized_keys_myserver << EOF
ssh-ed25519 AAAA... user@client
EOF'
```
**2. pipes.yaml 설정**
```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
```
### 양방향 키 인증 (가장 안전)
클라이언트도 키로, 백엔드도 키로 접속하는 방식입니다.
```yaml
- 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 인코딩된 키를 직접 설정할 수도 있습니다.
```yaml
- 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`)
```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`)
```ini
[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
```
## 관리 명령어
```bash
# 서비스 상태 확인
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
```
## 새 서버 추가
1. `pipes.yaml`에 새 파이프 추가:
```yaml
- from:
- username: "새서버"
to:
host: 10.x.x.x:22
username: root
ignore_hostkey: true
```
2. 서비스 재시작:
```bash
incus exec sshpiper -- systemctl restart sshpiper
```
## 사용 가능한 플러그인
| 플러그인 | 설명 |
|---------|------|
| `yaml` | YAML 파일 기반 라우팅 (현재 사용 중) |
| `docker` | Docker 컨테이너 라우팅 |
| `kubernetes` | Kubernetes Pod 라우팅 |
| `workingdir` | 작업 디렉토리 기반 라우팅 |
| `fixed` | 고정 대상 라우팅 |
| `failtoban` | 실패 시 차단 기능 |
| `username-router` | 사용자 이름 기반 라우팅 |
## Incus 프록시 설정
컨테이너에 `proxy2222` 디바이스가 설정되어 호스트의 2222 포트가 컨테이너의 2222 포트로 포워딩됩니다.
```bash
# 프록시 설정 확인
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
```
## 트러블슈팅
### 접속 불가 시
```bash
# 서비스 상태 확인
incus exec sshpiper -- systemctl status sshpiper
# 포트 리스닝 확인
incus exec sshpiper -- ss -tlnp | grep 2222
# 프로세스 확인
incus exec sshpiper -- ps aux | grep sshpiper
```
### 로그 확인
```bash
# 실시간 로그
incus exec sshpiper -- journalctl -u sshpiper -f
# 최근 에러
incus exec sshpiper -- journalctl -u sshpiper -p err --since "1 hour ago"
```
## 참고
- [SSHPiper GitHub](https://github.com/tg123/sshpiper)
- [SSHPiper 문서](https://github.com/tg123/sshpiper/wiki)