새로운 개발 건이 들어왔는데, 고객사 내부 네트워크 시스템에 접근해야 했다.
편하게 외부 컴포넌트라고 부르겠다.
그러나 본인 로컬에서는 고객사 내부 네트워크에 접근할 수 없었다.
대신 개발 서버는 고객사 내부 네트워크와 통신이 가능하므로 테스트가 가능하다.
그럼 외부 컴포넌트는 개발 서버에 배포하고만 테스트가 가능한걸까..?
오늘은 이에 관한 얘기를 해보고자 한다.
SSH 터널링 + hosts 파일을 이용한 로컬 개발 도메인 라우팅
현재 네트워크 구조를 보면 아래와 같다.
로컬(AWS VPN 접속) -> 개발 서버 (AWS VPC 개발 네트워크) -> 외부 컴포넌트(고객사 내부 네트워크)
또한 외부 컴포넌트는 443 포트만 허용한다.
이제 로컬에서 외부 컴포넌트에 접속할 수 있는 구조를 만드는 과정을 설명해보겠다.
1. Hosts 파일 : 도메인 -> 로컬 주소 (127.0.0.1)로 우회
브라우저, 애플리케이션은 DNS 쿼리보다 hosts 파일을 우선 참고한다.
본인은 mac 이라 /etc/hosts 파일에 아래와 같이 작성했다.
127.0.0.1 internal-component.example.com
이렇게 작성하면 로컬 PC가 internal-component.example.com에 접근할 때 DNS에 쿼리하지 않고 로컬 127.0.0.1로 요청을 보낸다.
2. SSH 로컬 포워딩: 로컬 포트 -> 원격 서버로 터널 생성
SSH 로컬 포워딩은 다음 원리로 동작한다.
- 로컬 특정 포트 (예시: 9999)에 들어온 트래픽을 SSH를 통해 암호화된 터널로 전송하고
- 개발 서버를 거쳐
- 외부 컴포넌트 특정 포트(필자의 경우 443)로 전달한다.
이를 통해 로컬의 127.0.0.1:9999 가 internal-component.example.com:443 동일해진다.
예시 명령어는 아래와 같다.
ssh -L 127.0.0.1:9999:internal-component.example.com:443 user@bastion-host
// 흐름
[로컬 PC]
↓ (1) hosts 파일: internal-component.example.com → 127.0.0.1:9999
[127.0.0.1:9999]
↓ (2) SSH 터널
[개발 서버]
↓ (3) 실제 요청
[고객사 내부 네트워크: internal-component.example.com:443]
필자는 .pem 키를 바인딩해야하고 여러 번 사용할 거 같아 Termius라는 소프트웨어를 사용했다.
https://termius.com/index.html
Termius - Modern SSH Client
Termius is a modern SSH client for Mac, Windows, Linux, iOS and Android. Connect with one click from any device.
termius.com
그럼 필자의 요청을 단순화하면 아래와 같다.
curl https://internal-component.example.com:9999
마지막으로 핵심 개념을 정리했다.
- AWS VPN: AWS VPC 내 개발 서버 접근
- SSH 터널링: 개발 서버를 경유지로 활용
- hosts 파일: SSL 인증서 검증 통과
주의할 부분
만약 1번을 진행하지 SSH 터널링만 진행하면 아래와 같은 에러들이 나올 것이다.
- SSL certificate problem: unable to get local issuer certificate
- SSL: no alternative certificate subject name matches target host name
브라우저나 애플리케이션은 도메인 이름을 사용하여 SSL 연결을 시도하는데, /etc/hosts 파일을 설정하지 않으면 internal-component.example.com이 로컬 IP(127.0.0.1)로 직접 연결된다.
그러나, 이 IP 주소로 접속하면 SSL 인증서에 해당 도메인 이름이 포함되어 있지 않기 때문에, "호스트 이름 불일치" 오류가 발생한다.
SSL 인증서는 도메인 이름(예: internal-component.example.com)과 IP 주소를 비교하는데, 이때 IP 주소로만 연결되면 인증서의 도메인 이름과 일치하지 않아서 오류가 발생하는 것이다.
이상으로 포스팅을 마칩니다. 감사합니다.