CML을 Teleport에 등록한 뒤, 외부에서도 브라우저로 CML에 접속할 수 있는 구조를 만들고 있었습니다.
목표는 단순했습니다.
외부 사용자가 다음 주소로 접속하면,
https://cml.console.nangman.cloud
Teleport 인증을 거친 뒤 내부망에 있는 CML 웹 UI로 연결되는 구조였습니다.
하지만 처음 설정을 마치고 접속해보니 예상과 다른 문제가 발생했습니다.
분명히 cml.console.nangman.cloud로 접속했는데,
브라우저 주소가 갑자기 내부 IP인 192.168.20.3으로 이동하려고 했습니다.
즉, 외부 사용자는 Teleport 주소로 들어왔는데,
중간에 CML이 자기 자신의 내부 주소로 브라우저를 다시 보내버리는 상황이었습니다.
1. 문제 상황
제가 원했던 접속 흐름은 다음과 같았습니다.
외부 사용자
→ cml.console.nangman.cloud
→ Teleport Proxy
→ Teleport Agent
→ 내부망 CML
→ CML 웹 UI
여기서 CML의 실제 내부 주소는 다음과 같았습니다.
https://192.168.20.3
이 주소는 Proxmox 내부망에서만 접근 가능한 주소입니다.
그래서 외부 사용자가 직접 192.168.20.3으로 접속할 수는 없습니다.
정상적인 흐름이라면 사용자의 브라우저 주소창에는 계속 다음 주소가 유지되어야 합니다.
https://cml.console.nangman.cloud
그리고 Teleport가 내부적으로만 CML의 실제 주소인 192.168.20.3으로 요청을 전달해야 합니다.
하지만 실제로는 CML 접속 과정에서 브라우저가 다음 주소로 이동하려고 했습니다.
https://192.168.20.3
이렇게 되면 외부 사용자는 접속할 수 없습니다.
192.168.20.3은 내부망 주소이기 때문에,
외부 사용자의 노트북이나 브라우저 입장에서는 접근할 수 없는 주소이기 때문입니다.
예시:
정상: 사용자 → cml.console.nangman.cloud → Teleport → CML
문제: 사용자 → cml.console.nangman.cloud → 192.168.20.3으로 이동
2. 리다이렉트란 무엇인가
먼저 리다이렉트 개념부터 정리해야 합니다.
리다이렉트는 웹 서버가 브라우저에게 “이 주소 말고 다른 주소로 다시 이동해”라고 알려주는 동작입니다.
예를 들어 사용자가 A 주소로 접속했는데,
서버가 B 주소로 이동하라고 응답하면 브라우저는 자동으로 B 주소로 이동합니다.
간단한 예시는 다음과 같습니다.
사용자 접속:
https://example.com/login
서버 응답:
https://example.com/nangman 로 이동하세요
브라우저 결과:
자동으로 /nangman 화면으로 이동
이런 리다이렉트 자체는 이상한 동작이 아닙니다.
로그인 후 대시보드로 이동하거나,
HTTP 접속을 HTTPS로 바꾸거나,
특정 경로를 다른 경로로 보내는 데 자주 사용됩니다.
문제는 리다이렉트의 목적지가 외부 사용자가 접근할 수 없는 내부 IP로 잡혔다는 점입니다.
3. 왜 192.168.20.3으로 튀었을까
Teleport를 통해 CML에 접속할 때 실제 요청 흐름은 다음과 같습니다.
브라우저
→ cml.console.nangman.cloud
→ Teleport Proxy
→ Teleport Agent
→ https://192.168.20.3
여기서 CML 입장에서는 자신이 192.168.20.3에서 서비스되고 있다고 생각합니다.
그래서 CML이 로그인 과정이나 페이지 이동 과정에서 리다이렉트 응답을 만들 때,
외부 주소인 cml.console.nangman.cloud가 아니라
자기 자신의 내부 주소인 192.168.20.3을 기준으로 응답할 수 있습니다.
CML이 브라우저에게 다음처럼 말하는 상황입니다.
“다음 페이지는 https://192.168.20.3으로 가세요.”
하지만 외부 사용자 입장에서는 192.168.20.3에 접근할 수 없습니다.
192.168.20.3은 사설 IP 대역이기 때문입니다.
사설 IP는 내부 네트워크에서만 사용하는 주소입니다.
집이나 회사, 홈랩 내부, IPSec 네트워크 내에서는 접근할 수 있지만, 인터넷에서는 직접 라우팅되지 않습니다.
그래서 외부 사용자의 브라우저가 192.168.20.3으로 이동하려고 하면 접속이 실패합니다.
4. 처음에 헷갈렸던 부분
처음에는 이 문제가 DNS 문제인지, 인증서 문제인지, Teleport 연결 문제인지 헷갈렸습니다.
왜냐하면 cml.console.nangman.cloud로 처음 접속은 되기 때문입니다.
Teleport 로그인도 되고, CML 화면으로 넘어가려는 것처럼 보입니다.
특히나 IPSec으로 연결된 네트워크 사용자 및 내부 사용자는 자연스럽게 접속이 되기 때문에
아무 문제가 없는 줄 알았습니다.
하지만 외부 사용자가 접속할 때
중간에 주소가 192.168.20.3으로 리다이렉트 되면서 접속이 깨지는 걸 확인 할 수 있었습니다.
이 상황을 단계로 나누면 다음과 같습니다.
1단계: cml.console.nangman.cloud 접속
→ 성공
2단계: Teleport 로그인
→ 성공
3단계: Teleport가 내부 CML로 요청 전달
→ 성공
4단계: CML이 내부 IP 기준으로 리다이렉트 응답
→ 문제 발생
Teleport 연결 자체가 안 된 것이 아니라, CML이 응답하는 리다이렉트 주소가 문제였습니다.
이걸 구분하는 것이 중요했습니다.
만약 Teleport Agent가 CML에 접근하지 못하는 문제라면
502, timeout, connection refused 등 같은 오류를 봐야 합니다.
하지만 이번 문제는 CML이 응답은 했는데, 응답 안에 들어있는 이동 주소가 내부 IP였던 것입니다.
5. 확인 방법
이 문제를 확인하는 가장 좋은 방법은 브라우저 개발자 도구의 Network 탭을 보는 것입니다.
Chrome 기준으로는 다음 순서로 확인할 수 있습니다.
브라우저에서 CML 접속
→ 개발자 도구 열기
→ Network 탭 선택
→ Preserve log 체크
→ 다시 접속 시도
→ 301, 302, 307, 308 응답 확인
→ Response Headers의 Location 값 확인
여기서 Location 값이 다음처럼 나오면 리다이렉트 문제가 맞습니다.
Location: https://192.168.20.3
또는 터미널에서 curl로도 확인할 수 있습니다.
예시는 다음과 같습니다.
curl -I https://cml.console.nangman.cloud
리다이렉트를 따라가며 확인하고 싶다면 다음처럼 볼 수도 있습니다.
curl -IL https://cml.console.nangman.cloud
만약 응답 중간에 Location 헤더가 내부 IP를 가리키고 있다면, CML이 내부 주소로 리다이렉트하고 있는 것입니다.
6. 해결 방향
해결 방향은 명확했습니다.
CML이 내부 IP로 리다이렉트하더라도,
외부 사용자의 브라우저는 계속 cml.console.nangman.cloud 기준으로 움직이게 만들어야 했습니다.
즉, 다음 흐름을 막아야 합니다.
cml.console.nangman.cloud
→ 192.168.20.3
그리고 다음 흐름으로 유지해야 합니다.
cml.console.nangman.cloud
→ Teleport
→ 내부 CML
이를 위해 Teleport Application 설정에서 public_addr와 rewrite.redirect를 사용했습니다.
public_addr는 외부 사용자가 접근할 공식 주소입니다.
rewrite.redirect는 내부 애플리케이션이 특정 주소로 리다이렉트하려고 할 때,
Teleport가 그 리다이렉트를 외부 주소 기준으로 다시 처리하도록 도와주는 설정입니다.
쉽게 말하면 다음과 같은 역할입니다.
CML:
“브라우저를 192.168.20.3으로 보내세요.”
Teleport:
“그 주소는 내부 주소니까, 외부 사용자에게는 cml.console.nangman.cloud 기준으로 바꿔서 전달해야겠다.”
7. 수정 전 설정
처음 설정은 대략 다음과 같은 형태였습니다.
app_service:
enabled: true
apps:
- name: cml
uri: https://192.168.20.3
insecure_skip_verify: true
이 설정만으로도 Teleport Agent가 내부 CML로 접근하는 것은 가능합니다.
하지만 외부에서 사용할 공식 주소와 내부 IP 리다이렉트 처리 방법이 명확히 들어가 있지 않았습니다.
그래서 CML이 자기 기준으로 192.168.20.3을 리다이렉트 주소로 응답하면,
브라우저가 그대로 내부 IP로 이동하려는 문제가 생겼습니다.
8. 수정 후 설정
문제를 해결하기 위해 설정을 다음처럼 수정했습니다.
app_service:
enabled: true
apps:
- name: cml
uri: https://192.168.20.3
public_addr: cml.console.nangman.cloud
insecure_skip_verify: true
rewrite:
redirect:
- "192.168.20.3"
여기서 핵심은 두 가지입니다.
public_addr: cml.console.nangman.cloud
rewrite:
redirect:
- "192.168.20.3"
public_addr는 사용자가 접속할 외부 주소를 명시합니다.
rewrite.redirect는 CML이 192.168.20.3으로 리다이렉트하려고 할 때,
Teleport가 해당 리다이렉트를 처리할 수 있게 해줍니다.
만약 CML이 포트까지 포함해서 리다이렉트한다면,
상황에 따라 다음처럼 포트를 포함해서 추가해야 할 수도 있습니다.
rewrite:
redirect:
- "192.168.20.3"
- "192.168.20.3:443"
제 경우에는 CML이 사용하는 내부 주소 기준으로 리다이렉트 대상이 잡혀 있었기 때문에,
해당 내부 주소를 rewrite.redirect에 추가했습니다.

9. 설정 적용
teleport.yaml을 수정한 뒤에는 Teleport 서비스를 재시작해야 합니다.
설정 파일만 바꾼다고 바로 반영되는 것은 아닙니다.
다음 명령어로 서비스를 재시작했습니다.
sudo systemctl restart teleport
그리고 상태를 확인했습니다.
sudo systemctl status teleport --no-pager
로그도 함께 확인했습니다.
sudo journalctl -u teleport -f
여기서 설정 파일에 YAML 들여쓰기 오류가 있으면 Teleport가 정상적으로 올라오지 않을 수 있습니다.
특히 app_service 아래의 apps, name, uri, public_addr, rewrite 들여쓰기가 중요합니다.
YAML은 중괄호로 구조를 구분하는 방식이 아니라 들여쓰기로 구조를 구분하기 때문에,
공백이 틀리면 전혀 다른 설정으로 인식되거나 오류가 발생할 수 있습니다.
그리고 저는 Teleport Agent가 Ubuntu Server가 재부팅을 해도 자동으로 올라오게 하여
서비스를 올리고 싶었기 때문에
다음 순으로 명령어를 추가적으로 실행 했습니다.
sudo vi /etc/systemd/system/teleport-agent.service
//teleport-agent를 "서비스 프로그램"으로 인식하고, 부팅 시 자동 실행하거나 죽으면 다시 실행할 수 있게 해주는 설정 파일 생성
sudo systemctl daemon-reload
//systemd에게 새로 만들거나 수정한 .service 파일을 다시 읽으라고 하는 명령어
sudo systemctl enable teleport-agent
//teleport-agent 서비스를 서버 부팅 시 자동으로 켜지게 등록하는 명령어
sudo systemctl start teleport-agent
//teleport-agent 서비스를 지금 바로 실행하는 명령어
sudo systemctl status teleport-agent
//teleport-agent 서비스가 정상 실행 중인지 확인하는 명령어

최종적으로 재부팅 시 자동 실행 및 Teleport status가 active인걸 확인할 수 있었습니다.
10. 수정 후 확인
설정을 반영한 뒤 다시 브라우저에서 접속했습니다.
https://cml.console.nangman.cloud
이번에는 브라우저 주소가 192.168.20.3으로 바뀌지 않고,
cml.console.nangman.cloud 주소를 유지한 상태로 CML 화면이 열렸습니다.
즉, 외부 사용자는 내부 IP를 직접 알 필요 없이 Teleport 주소만으로 CML에 접근할 수 있게 되었습니다.
정상 흐름은 다음과 같습니다.
사용자 브라우저
→ https://cml.console.nangman.cloud
→ Teleport 로그인
→ Teleport Proxy
→ Teleport Agent
→ https://192.168.20.3
→ CML 웹 UI
브라우저 주소창에는 계속 다음 주소가 보입니다.
https://cml.console.nangman.cloud
하지만 내부적으로는 Teleport Agent가 CML의 실제 내부 주소로 요청을 전달합니다.
이게 제가 원했던 구조였습니다.

11. 이 문제를 통해 이해한 것
이번 문제를 겪으면서 Teleport Application Access의 동작 방식을 더 명확히 이해하게 되었습니다.
처음에는 Teleport를 단순한 리버스 프록시처럼 생각했습니다.
하지만 실제로는 외부 주소, 내부 URI, 애플리케이션이 응답하는 리다이렉트 주소까지 함께 고려해야 했습니다.
특히 내부 서비스가 자기 자신의 주소를 기준으로 절대 URL을 만들어 응답하는 경우,
외부 접속 주소와 내부 주소가 달라지면서 문제가 생길 수 있습니다.
이번 문제의 핵심은 다음과 같습니다.
외부 접속 주소:
https://cml.console.nangman.cloud
내부 실제 주소:
https://192.168.20.3
문제 원인:
CML이 내부 실제 주소인 192.168.20.3 기준으로 리다이렉트 응답
해결 방법:
Teleport app 설정에 public_addr와 rewrite.redirect 추가
이렇게 정리할 수 있습니다.
12. 마무리
이번 글에서는 Teleport로 CML을 등록한 뒤,
접속 과정에서 브라우저가 내부 IP인 192.168.20.3으로 이동하려던 문제를 해결한 과정을 정리했습니다.
처음에는 Teleport 연결 자체가 잘못된 줄 알았지만,
실제 원인은 CML이 내부 주소 기준으로 리다이렉트 응답을 보내는 것이었습니다.
(설정 이후에도 제 브라우저에는 캐시로 인하여 사설 IP 주소로 떠서 또 혼자 엄청 삽질했습니다.)
이 문제는 Teleport Application 설정에 rewrite.redirect를 추가하여 해결할 수 있었습니다.
최종적으로 접속 흐름은 다음처럼 정리할 수 있습니다.
외부 사용자
→ cml.console.nangman.cloud
→ Teleport 인증
→ Teleport Proxy
→ Teleport Agent
→ 내부망 CML
→ CML 웹 UI
그리고 브라우저 주소창은 계속 외부 주소인 cml.console.nangman.cloud를 유지합니다.
이번 트러블슈팅에서 얻은 핵심은 다음과 같습니다.
1. 외부 주소와 내부 주소가 다르면 (특히 사설 IP로 리다이렉트시) 리다이렉트 문제가 생길 수 있음
2. CML 같은 웹 애플리케이션은 자기 내부 주소 기준으로 리다이렉트할 수 있음
3. 브라우저가 내부 IP로 이동하면 외부 사용자는 접근할 수 없음
4. Teleport의 public_addr는 외부 사용자가 접근할 공식 주소를 지정함(proxy측에서 매핑설정이 있다면 생략가능)
5. rewrite.redirect는 내부 주소로 튀는 리다이렉트를 보정하는 데 사용함
6. 설정 변경 후에는 systemctl restart teleport로 서비스를 재시작해야 함
7. 문제 확인은 브라우저 개발자 도구 Network 탭이나 curl -IL로 할 수 있음
결국 이번 문제는 “접속은 되었지만, 이동할 주소가 잘못된 문제”였습니다.
CML은 내부망에 그대로 두고, 외부 사용자는 Teleport 주소만 사용하게 만드는 것이 목표였기 때문에,
ewrite.redirect 설정이 핵심이었습니다.
이렇게 설정한 뒤에는 외부에서도
cml.console.nangman.cloud 주소를 유지한 상태로 CML 웹 UI에 정상적으로 접속할 수 있었습니다.
'TroubleShooting' 카테고리의 다른 글
| Proxmox VE 9 구독 없이 apt update 실패 해결하기 (0) | 2026.05.07 |
|---|