diff --git a/infra/sshpiper.md b/infra/sshpiper.md new file mode 100644 index 0000000..edcc38a --- /dev/null +++ b/infra/sshpiper.md @@ -0,0 +1,125 @@ +--- +title: sshpiper SSH 리버스 프록시 +updated: 2026-03-26 +tags: [infra, ssh, proxy, k3s] +--- + +## 개요 + +sshpiper는 SSH를 위한 리버스 프록시. HTTP의 nginx처럼 SSH 연결을 중개하고 라우팅한다. +- GitHub: https://github.com/tg123/sshpiper +- 라이센스: MIT + +## 배포 정보 + +K3s 클러스터(kr3 컨텍스트)에 Helm으로 설치 (2026-03-26) + +| 항목 | 값 | +|------|-----| +| Namespace | sshpiper | +| Chart | sshpiper/sshpiper 0.4.6 | +| App | sshpiperd v1.5.0 | +| Image | farmer1992/sshpiperd:v1.5.0 | +| Plugin | kubernetes (CRD 기반) | +| Service | NodePort 2222 → 31840 | +| Helm repo | https://tg123.github.io/sshpiper-chart | + +## 라우팅 구조 + +Pipe CRD (`pipes.sshpiper.com/v1beta1`)로 사용자명 기반 라우팅: + +``` +ssh jp1@호스트:31840 → root@incus-jp1(100.109.123.1:22) +``` + +## 인증 방식 + +### 패스워드 인증 (passthrough) + +- 별도 키/시크릿 설정 불필요, Pipe CRD만 만들면 끝 +- 클라이언트가 입력한 패스워드를 sshpiper가 그대로 업스트림에 전달 + +### 키 기반 인증 (두 번 인증) + +``` +유저(개인키A) → sshpiper(공개키A로 검증) → sshpiper(개인키S로 업스트림 접속) → 서버(공개키S 등록) +``` + +- 키는 전달이 아니라 sshpiper가 자체 키로 업스트림에 별도 인증 +- `from.authorized_keys_data`: 유저의 공개키 등록 +- `to.private_key_secret`: sshpiper 전용 개인키 (K8s Secret) +- 업스트림 서버의 `authorized_keys`에 sshpiper 공개키 등록 +- sshpiper 키 페어 하나로 모든 Pipe에서 공유 가능 + +| 구간 | 패스워드 방식 | 키 방식 | +|------|-------------|---------| +| 클라이언트 → sshpiper | 패스워드 통과(검증 안 함) | 유저 공개키로 검증 | +| sshpiper → 서버 | 패스워드 그대로 전달 | sshpiper 전용 개인키로 별도 인증 | + +## 지원 기능 + +SSH 세션을 통째로 프록시하므로 SSH로 할 수 있는 것 전부 지원: +- 포트포워딩 (로컬 -L, 리모트 -R, 다이나믹 -D) +- SCP, SFTP +- 세션 녹화 (asciicast/typescript) + +## 현재 Pipe 목록 + +- pipe-jp1: `jp1` → `root@100.109.123.1:22` (패스워드 인증) + +## Pipe CRD 예시 + +### 패스워드 방식 + +```yaml +apiVersion: sshpiper.com/v1beta1 +kind: Pipe +metadata: + name: pipe-jp1 + namespace: sshpiper +spec: + from: + - username: jp1 + to: + host: 100.109.123.1:22 + ignore_hostkey: true + username: root +``` + +### 키 방식 + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: sshpiper-key + namespace: sshpiper +type: Opaque +data: + ssh-privatekey: +--- +apiVersion: sshpiper.com/v1beta1 +kind: Pipe +metadata: + name: pipe-jp1 + namespace: sshpiper +spec: + from: + - username: jp1 + authorized_keys_data: "ssh-ed25519 AAAA... user-pubkey" + to: + host: 100.109.123.1:22 + ignore_hostkey: true + username: root + private_key_secret: + name: sshpiper-key +``` + +## 관리 명령 + +```bash +kubectl get pipes -n sshpiper # Pipe 목록 +kubectl get pipes -n sshpiper -o yaml # 상세 설정 +helm get values sshpiper -n sshpiper # Helm 설정값 +helm get manifest sshpiper -n sshpiper # 전체 매니페스트 +```