SSH 로컬 및 원격 포트 포워딩을 통한 터널링 구현
SSH 포트 포워딩을 사용하여 안전한 네트워크 액세스와 방화벽 우회를 구현하세요. 이 포괄적인 가이드는 로컬(`-L`) 및 원격(`-R`) SSH 터널링 기술의 실제 구현을 자세히 설명합니다. 필수 구문을 배우고, 원격 서비스 액세스와 로컬 서비스 노출의 주요 차이점을 이해하며, 데이터베이스 연결 보안 또는 개발 환경 공유와 같은 작업에 대한 명확한 예제를 확인하세요. 키 기반 인증을 사용하여 지속적이고 안전한 백그라운드 터널을 생성하기 위한 중요한 모범 사례를 포함합니다.
SSH 로컬 및 원격 포트 포워딩을 통한 터널링 구현
SSH 포트 포워딩은 방화벽, 개인 서브넷 또는 어색한 공급업체 네트워크가 간단한 경로를 차단할 때까지 잊고 지내는 도구 중 하나입니다. 그러면 가장 빠른 깔끔한 해결책이 됩니다. 배스천 호스트를 통해 데이터베이스에 도달하거나, 노트북에서 개인 관리 페이지를 테스트하거나, 로컬 개발 서버를 노트북에 직접 연결할 수 없는 머신에 노출하는 데 사용할 수 있습니다.
기본 아이디어는 간단합니다. SSH는 연결의 한쪽에서 수신 포트를 열고 암호화된 SSH 세션을 통해 트래픽을 다른 쪽의 대상으로 전달합니다. 사람들을 혼란스럽게 하는 부분은 방향입니다. -L을 사용한 로컬 포워딩은 머신이 SSH 서버 근처의 무언가에 도달할 수 있게 합니다. -R을 사용한 원격 포워딩은 SSH 서버 근처의 무언가가 머신 근처의 무언가에 도달할 수 있게 합니다.
로컬 포워딩: 원격 서비스를 노트북으로 가져오기
필요한 서비스가 SSH 서버에서 도달할 수 있지만 워크스테이션에서는 도달할 수 없을 때 로컬 포워딩을 사용하세요.
ssh -L 15432:db.internal.example:5432 [email protected]
이 연결 후 노트북은 127.0.0.1:15432에서 수신 대기합니다. psql, DBeaver 또는 애플리케이션 구성을 해당 로컬 포트로 지정하면 SSH가 트래픽을 bastion.example.com으로 보내고 배스천은 db.internal.example:5432에 대한 연결을 엽니다.
명령을 왼쪽에서 오른쪽으로 읽으세요:
내 머신의 로컬 포트 : SSH 서버가 보는 대상 호스트 : 대상 포트
이 "SSH 서버가 보는 대로"라는 세부 사항이 중요합니다. 데이터베이스가 개인 네트워크 내에서만 db.internal.example로 명명된 경우 노트북이 해당 이름을 확인할 필요가 없습니다. 배스천이 합니다. 데이터베이스가 배스천의 localhost에서만 수신 대기하는 경우 대신 다음을 사용하세요:
ssh -L 15432:127.0.0.1:5432 [email protected]
로컬 포워딩은 일반적으로 수신 포트가 워크스테이션에 있기 때문에 더 안전한 기본값입니다. 기본적으로 OpenSSH는 로컬 포워딩된 포트를 루프백 인터페이스에 바인딩하므로 Wi-Fi 또는 사무실 네트워크의 다른 머신이 터널을 사용할 수 없습니다. 명시적으로 지정할 수 있습니다:
ssh -L 127.0.0.1:15432:db.internal.example:5432 [email protected]
정말로 터널을 다른 호스트와 공유하려는 경우가 아니라면 0.0.0.0에 바인딩하지 마세요. 다음과 같은 명령은 노트북에서 포트 15432에 도달할 수 있는 모든 사람에게 노트북을 개인 데이터베이스에 대한 프록시로 만듭니다:
ssh -L 0.0.0.0:15432:db.internal.example:5432 [email protected]
실험실에서는 유용할 수 있습니다. 일반 워크스테이션에서는 거의 원하는 것이 아닙니다.
원격 포워딩: 서버를 통해 로컬 서비스 노출
원격 포워딩은 수신 측을 뒤집습니다. 서비스가 머신에서 실행 중이지만 SSH 서버 근처의 누군가 또는 무언가가 그 서비스에 도달해야 할 때 사용하세요.
ssh -R 18080:127.0.0.1:3000 [email protected]
이것은 public.example.com이 포트 18080에서 수신 대기하도록 요청합니다. 해당 포트에 대한 연결은 SSH를 통해 노트북의 127.0.0.1:3000으로 다시 전달됩니다. 이는 웹훅 수신기를 테스트하거나, 임시 데모를 공유하거나, 노트북에 직접 호출할 수 없는 스테이징 시스템의 콜백을 디버깅할 때 유용합니다.
한 가지 일반적인 놀라움이 있습니다. 원격 포워딩된 포트는 일반적으로 SSH 서버의 루프백에 바인딩됩니다. 즉, public.example.com에서 실행할 때 curl http://127.0.0.1:18080은 작동하지만 브라우저에서 http://public.example.com:18080은 작동하지 않을 수 있습니다.
원격 포워딩된 포트를 다른 머신에서 도달할 수 있게 하려면 SSH 서버가 이를 허용해야 합니다. /etc/ssh/sshd_config에서 관련 설정은 일반적으로 다음과 같습니다:
GatewayPorts clientspecified
그런 다음 공개 바인딩을 요청할 수 있습니다:
ssh -R 0.0.0.0:18080:127.0.0.1:3000 [email protected]
주의해서 사용하세요. 서버를 통해 로컬 서비스를 게시하는 것입니다. 앞에 방화벽을 두고, 높은 무작위 포트를 사용하며, 관리 도구, 개발 데이터베이스 또는 인증되지 않은 앱을 인터넷에 노출하지 마세요.
터널을 지루하고 안정적으로 유지하기
장기 실행 터널의 경우 일반적으로 원격 호스트에서 셸을 원하지 않습니다:
ssh -N -L 15432:db.internal.example:5432 [email protected]
-N은 "원격 명령을 실행하지 않음"을 의미합니다. 터널이 NAT, VPN 또는 유휴 TCP 세션을 끊는 클라우드 로드 밸런서를 통과할 때 keepalive를 추가하세요:
ssh -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 15432:db.internal.example:5432 \
[email protected]
무인 사용의 경우, 일반 ssh -f 명령보다 systemd 사용자 서비스, autossh 또는 프로세스 감독자를 선호하세요. -f로 백그라운드 실행은 작동하지만 실패한 시작과 오래된 터널을 알아차리기 어렵게 만듭니다.
ssh -fN -L 15432:db.internal.example:5432 [email protected]
-fN을 사용하는 경우 먼저 -f 없이 동일한 명령을 테스트하세요. 비밀번호 프롬프트, 알 수 없는 호스트 키 프롬프트 및 포트 충돌은 포그라운드에서 진단하기 훨씬 쉽습니다.
문제 해결 체크리스트
터널이 연결되었지만 애플리케이션이 여전히 실패하는 경우 추측 대신 각 홉을 확인하세요.
먼저 로컬 리스너가 존재하는지 확인하세요:
ss -ltnp | grep 15432
그런 다음 SSH 서버에서 대상을 테스트하세요:
ssh [email protected] 'nc -vz db.internal.example 5432'
그것이 실패하면 SSH 포워딩이 문제가 아닙니다. 배스천이 서비스에 도달할 수 없거나, 이름이 거기서 확인되지 않거나, 보안 그룹이 포트를 차단하거나, 서비스가 잘못된 인터페이스에 바인딩되어 있습니다.
리스너가 시작되지 않으면 로컬 포트가 이미 사용 중일 수 있습니다:
lsof -iTCP:15432 -sTCP:LISTEN
원격 포워딩이 remote port forwarding failed와 같은 메시지와 함께 실패하면 서버가 TCP 포워딩을 차단할 수 있습니다. sshd_config에서 AllowTcpForwarding을 확인하고 요청된 포트가 이미 사용 중인지 확인하세요.
유지할 가치가 있는 보안 습관
키 기반 인증을 사용하고 터널에 사용되는 계정을 제한하세요. 전용 터널 사용자의 경우 제한된 셸 액세스, 방화벽 규칙 및 필요한 방향에 따라 PermitOpen 또는 PermitListen과 같은 SSH 옵션을 결합할 수 있습니다. 이러한 제어는 편의 터널이 광범위한 네트워크 액세스로 변하는 것을 방지합니다.
노트나 런북에서 터널을 명령이 아닌 의도로 이름을 지정하세요. "배스천을 통한 프로덕션 보고 복제본에 대한 노트북 15432"는 셸 기록의 미스터리 ssh -L 줄보다 감사하기 쉽습니다.
로컬 포워딩은 안쪽으로 도달하는 데 도움이 됩니다. 원격 포워딩은 다른 사람이 당신 쪽으로 다시 도달할 수 있게 합니다. 이 구분이 명확해지면 대부분의 SSH 터널링 문제는 어느 쪽이 수신 대기하는지, 어느 쪽이 대상을 확인하는지, 그리고 그 사이에 어떤 방화벽이 있는지 확인하는 문제가 됩니다.
볼 수 있는 몇 가지 실제 패턴
일반적인 프로덕션 패턴은 데이터베이스 유지 관리 터널입니다. 개인 서브넷에 보고 복제본, 엄격한 SSH 액세스가 있는 배스천 호스트, 노트북에 분석가 도구가 있습니다. 로컬 포워딩이 깔끔하게 맞습니다:
ssh -N -L 127.0.0.1:15432:reporting-db.internal:5432 [email protected]
노트북의 애플리케이션은 개인 데이터베이스 호스트 이름이 아닌 127.0.0.1을 사용해야 합니다. 도구가 데이터베이스 호스트에 대한 SSL 호스트 이름 확인을 요구하는 경우 데이터베이스 호스트 이름으로 연결하고 로컬 호스트 항목을 추가하거나 올바른 SSL 모드로 클라이언트를 구성해야 할 수 있습니다. 터널은 TCP 바이트만 이동합니다. 데이터베이스 프로토콜 세부 정보를 다시 쓰지 않습니다.
또 다른 패턴은 임시 웹훅 수신기입니다:
ssh -N -R 127.0.0.1:19090:127.0.0.1:9090 [email protected]
이 버전에서 포워딩된 포트는 의도적으로 게이트웨이 자체에서만 사용할 수 있습니다. 그런 다음 게이트웨이의 스테이징 서비스가 http://127.0.0.1:19090/hook을 호출하도록 구성할 수 있습니다. 이는 포트를 전체 네트워크에 게시하는 것보다 안전합니다.
짧은 공개 데모의 경우 방화벽 규칙을 추가한 후에만 공개 바인딩을 사용하세요:
ssh -N -R 0.0.0.0:19090:127.0.0.1:3000 [email protected]
그런 다음 게이트웨이를 제한하세요:
sudo ufw allow from 203.0.113.40 to any port 19090 proto tcp
이 제한 없이 게이트웨이에 도달할 수 있는 사람은 누구나 포워딩된 서비스를 시도할 수 있습니다.
SSH 터널링이 해결하지 못하는 것
SSH 포워딩은 서비스 인증을 대체하지 않습니다. 데이터베이스가 비밀번호 없이 로컬 연결을 허용하는 경우 터널이 의도한 것보다 더 멀리 약한 신뢰 경계를 확장할 수 있습니다. 로컬 개발 앱에 로그인 페이지가 없는 경우 원격 포워딩이 그대로 게시할 수 있습니다.
또한 불안정한 대상을 안정적으로 만들지 않습니다. 배스천이 내부 이름을 확인할 수 없거나, 서비스가 다운되었거나, 보안 그룹이 경로를 차단하는 경우 터널이 성공적으로 설정될 수 있지만 애플리케이션은 실패합니다. 이것이 SSH 서버에서 테스트하는 것이 매우 유용한 이유입니다.
마지막으로 터널은 잊기 쉽습니다. 공유 점프 호스트의 오래된 터널은 예상치 못한 포트를 열어둘 수 있습니다. 장기 실행 작업의 경우 명확한 이름, 소유자 및 다시 시작 정책이 있는 서비스 파일에 명령을 넣으세요. 임시 작업의 경우 작업이 완료되면 닫고 ss -ltnp로 리스너가 사라졌는지 확인하세요.