기존 HTTP 프록시로의 SSH 로컬 포워딩: 두 개의 loopback 주소
SSH 호스트의 기존 프록시는 하나의 로컬 포워딩으로 하나의 애플리케이션에 서비스를 제공할 수 있습니다. 두 loopback 주소와 프록시 프로토콜을 구분하세요.
승인된 프록시는 점프 호스트에서 실행되며 여기서는 loopback에서만 수신하므로, 그 머신 밖에서는 아무것도 접근할 수 없습니다. VPN이나 새 프록시는 필요하지 않습니다. 필요한 것은 그 머신의 포트 하나를 자신의 포트 하나로 가져오는 것입니다. 로컬 포워딩이 바로 그 일을 하며, 명령 하나와 애플리케이션 설정 하나면 됩니다. 혼란은 보통 어느 loopback 주소가 어느 머신에 속하는지 뒤바꾸는 데서 생깁니다.
고정 프록시가 이미 있는지 판단하세요
이 기법은 이미 실행 중인 서비스를 포워딩합니다. 원격 호스트에 SSH 데몬만 있고 프록시가 없다면, 아무리 포워딩해도 프록시가 생기지 않으며 연결은 원격 쪽에서 거부됩니다. 프록시가 바인딩되어 있는지, 포트가 무엇인지, 127.0.0.1에서 수신하는지 특정 인터페이스 주소에서 수신하는지 확인하세요. 포워딩이 겨냥해야 할 주소가 바로 그것입니다.
이것을 먼저 확인하면 한 번도 무엇에도 연결된 적 없는 터널을 디버깅하지 않아도 됩니다.
포워딩을 구성하고 명령을 읽으세요
원하는 형태는 노트북의 loopback 포트를 바인딩하고, 서버 쪽에서 프록시 주소로 서버가 보는 그대로 연결합니다.
ssh -NT -o ControlPath=none -o ExitOnForwardFailure=yes \
-L 127.0.0.1:13128:127.0.0.1:3128 [email protected]-N은 원격 명령을 억제하고 -T는 termios 할당을 억제합니다. 셸이 아니라 터널이 필요하기 때문입니다. 첫 번째 loopback 주소는 노트북이 수신하는 곳이고, 두 번째는 SSH 서버가 해석하므로 그곳의 127.0.0.1은 그 머신의 프록시를 뜻합니다. ExitOnForwardFailure은 로컬 포트가 이미 사용 중이면 아무것도 포워딩하지 않는 세션을 시작하는 대신 명령을 크게 실패하게 만듭니다. 대상 주소는 서버가 해석하는 방식으로 쓰세요. 노트북만 해석할 수 있는 이름은 반대편에서 실패합니다.
이 중 무엇이든 동작하기 전에 서버 자체의 정책이 적용됩니다. AllowTcpForwarding이 이를 허용해야 하고, PermitOpen는 세션이 도달할 수 있는 대상과 포트를 제한할 수 있으므로 클라이언트가 받아들인 포워딩도 서버가 거부할 수 있습니다. 거부는 클라이언트에서 포워딩 또는 채널 오류로 나타나며, 그 메시지를 읽는 것이 명령을 편집하는 것보다 빠릅니다.
애플리케이션 하나를 포워딩으로 향하게 하세요
http://127.0.0.1:13128의 HTTP 프록시를 사용하도록 애플리케이션을 구성하고, 원격 프록시가 요구하면 자격 증명도 넣으세요. HTTPS 대상에 대해서는 애플리케이션 자체의 인증서 검증을 유지하세요. 프록시 터널이 그것을 대체하지 않습니다. 이것은 한 서비스의 고정 포워딩이므로 애플리케이션에 프록시가 있다고 알려야 하며, 스스로 찾게 두어서는 안 됩니다.
영구적인 설정 전에 빠른 확인: curl -x http://127.0.0.1:13128 -I https://example.com, 프록시가 지원해야 하는 HTTP CONNECT 메서드를 시험합니다.
권한은 원래 있던 곳에 두세요
원격 프록시는 여전히 어떤 대상과 메서드를 허용할지 결정하며, SSH 로그인이 모든 계정에 조용히 일반 웹 릴레이를 부여해서는 안 됩니다. 노트북에서 127.0.0.1에 바인딩하면 포트를 로컬 네트워크에 공개하지 않지만, 같은 머신의 다른 프로세스로부터 포트를 비공개로 만들지는 않습니다. 그 바인딩을 wildcard 주소로 바꿔 프록시를 공유하는 것이 관리되지 않는 개방형 릴레이가 생기는 방식입니다.
SSH 전송은 서버까지의 구간을 보호합니다. 그 지점을 넘으면 프록시가 자체 연결을 열므로, 대상으로 가는 일반 HTTP 요청은 첫 구간이 암호화되었더라도 서버 너머에서는 일반 상태로 남습니다.
양쪽 끝을 확인한 뒤 정리하세요
로컬 터널 설정과 원격 서비스의 성공은 서로 다른 결과이며, 명령의 종료 상태는 첫 번째에 대해서만 알려줍니다. ss -ltn로 리스너가 있는지 확인한 다음, 허용된 애플리케이션 요청과 프록시가 거부해야 할 요청을 보내세요. 둘 다 예상대로 동작하면 경로는 진짜입니다. 터널이 살아 있는데 모든 요청이 실패하면 프록시가 거부하고 있거나 대상에 도달하지 못하는 것입니다.
끝나면 터널을 소유한 SSH 프로세스를 중지하고, 애플리케이션에서 프록시 설정을 제거하고, 작업보다 오래 사는 리스너를 남기지 말고 로컬 포트가 사라졌는지 확인하세요.