stunnel 뒤의 OpenVPN: 1194번 포트가 아니라 래퍼를 전달하십시오
리스너 둘, 포트 셋. 전달이 어디에 도착하는지, 래퍼가 어디에 바인딩되는지, 어디로 연결하는지, 로컬 테스트가 무엇을 건너뛰었는지, 그리고 두 신원을 확인하십시오.
TLS 래퍼를 OpenVPN 앞에 두면 배포에는 두 번째 리스너가 생기며, 그중 하나만 인터넷을 향해야 합니다. 터널이 같은 머신에서는 되고 외부에서는 실패한다면, 전달은 보통 둘 중 잘못된 쪽을 향하고 있습니다. 맞춰져야 하는 것은 사슬로, 공개 규칙이 래퍼에 도달하고 래퍼 자체의 백엔드 연결이 실제 VPN 소켓에 도달합니다. 네 번의 도약이 이 사슬을 지탱하며, 그중 어느 하나만 어긋나도 조사는 일찍 끝납니다.
소켓 둘, 소유자 둘, 하나는 공개
래퍼는 외부 연결을 위해 TLS를 종료하고 복호화된 바이트 스트림을 평범한 OpenVPN TCP 리스너에 넘깁니다. 이 둘은 별도의 설정 파일을 가진 별도의 소켓이므로, 하나를 편집해도 다른 하나는 그대로이며 여전히 겉보기에는 건강합니다. 또한 하나를 다른 하나 없이 바꾸면 둘이 어긋날 수 있다는 뜻이기도 합니다.
머신 자체에서 작업하는 것은 공개 경로에 대해 거의 아무것도 증명하지 못합니다. 원래 포트로의 직접 연결은 래퍼를 건너뛰고, 래퍼의 LAN 주소로의 연결은 변환을 건너뛰며, 외부 사용자가 하는 일을 실제로 해 보는 것은 클라이언트 측의 완전한 구성뿐입니다. 이름도 주의해서 읽어야 하며, localhost 은 그 구성 요소를 실행하는 호스트를 뜻하고 우연히 입력하고 있는 호스트가 아닙니다. 자기가 덮은 도약을 적지 않은 테스트는 서로 다른 두 가지를 비교하도록 부추기므로, 이 구분을 메모에 남기십시오.
전달이 실제로 도착하는 곳
사슬은 같은 번호라도 양 끝에서 다른 의미일 수 있으므로 세 개의 포트 번호보다 네 번의 도약으로 붙잡는 편이 쉽습니다. 표를 행마다 읽으면, 각 행은 연결을 받아들이고 다음 연결을 열어야 하는 하나의 소켓입니다. 어떤 행이 잘못된 상대를 향하면, 마지막 열의 증상이 사용자가 보고하는 것입니다.
| Hop | Listens on | Must reach | Symptom when it points elsewhere |
|---|---|---|---|
| Client machine | A local plaintext port | The wrapper's public TLS address | Plain text offered to a TLS endpoint |
| Router forward | Public TCP 443 | The wrapper host on its translated port | Wrapper records no connection at all |
| Wrapper, server mode | Its accepted port, 8443 here | The native VPN socket on loopback | Handshake completes, then silence |
| Native VPN listener | Loopback TCP port | Its peer, over TCP only | A UDP socket behind a byte-stream relay |
래퍼가 아니라 원래 VPN 포트를 겨냥하는 규칙은 TLS 종료를 완전히 건너뛰는데, 이것이 이 실수의 가장 흔한 형태이며, 클라이언트는 OpenVPN 프레이밍을 기대하는 리스너와 핸드셰이크를 열어 연결이 열린 뒤 멈출 수 있습니다. 번역된 포트는 다음에 그 파일을 편집할 사람이 다른 번호를 골랐을 수 있으므로 기억이 아니라 래퍼의 설정 파일과 대조해 확인하십시오. 아래 두 명령은 그 질문의 양면을 동시에 보여 줍니다.
grep -nE '^[[:space:]]*(accept|connect)' /etc/stunnel/stunnel.conf
ss -lntp | grep -E ':443|:8443|:1194'
당신을 거부하는 바인드 주소
127.0.0.1 에 바인딩된 accept 줄은 호스트 자신에게만 응답하므로, LAN 주소로 들어온 전달은 연결할 수 없고 클라이언트는 패킷 필터 문제처럼 들리는 거부를 보게 됩니다. 소켓이 더 저렴한 답이므로 방화벽을 만지기 전에 소켓을 보십시오. 래퍼를 전달이 겨냥하는 인터페이스에 바인딩하거나, loopback에 둔 채 전달이 실제로 동작하는 무언가를 거쳐 loopback에 닿게 하십시오. 이 둘은 서로 다른 설계이며, 각각 자기 규칙이 필요합니다.
둘을 섞는 것이 바로 동작하는 래퍼가 외부에서 닿을 수 없게 되는 방식이며, 모든 파일은 올바르게 보입니다. 아래 확인은 명령 하나이고, 방화벽 규칙 검토로는 답할 수 없는 질문에 답합니다. 출력이 loopback 주소를 보여 주는데 전달이 LAN 주소를 겨냥한다면, 수정은 accept 줄에 속하며 패킷 필터가 아닙니다.
ss -lntp '( sport = :8443 )'
로컬 테스트가 실제로 증명한 것
자기가 덮은 도약을 적지 않은 성공은 다른 도약에 대한 증거가 아닙니다. 테스트가 어떤 주소를 썼고 어떤 프로세스가 응답했는지 적어 두십시오. 그다음, 헤어핀 동작은 라우터마다 다르고 LAN을 한 번도 벗어나지 않은 연결도 전달이 전혀 개입하지 않은 채 클라이언트를 만족시킬 수 있으므로, 같은 Wi-Fi의 휴대폰이 아니라 네트워크 밖에서 반복하십시오. 오직 그 두 번째 시도만이 외부인이 걷는 경로를 시험합니다.
시도가 실패하면, 래퍼의 수락 및 연결 줄, 이어서 VPN 데몬 자체의 세션 로그로 하나의 연결을 두 로그에서 따라가십시오. 아무것도 기록하지 않는 첫 경계가 다음 변경의 자리입니다. OpenVPN이 피어 옵션을 비교하기 시작하면 그 메시지는 해당 구현의 규칙으로 판단하십시오. link-mtu 불일치 경고가 자동으로 치명적인 것은 아니고, link-mtu를 1500에 고정해도 단편화가 멈췄다는 증거가 되지 않으며, 암호 협상은 라우터의 전달이 아니라 내부 OpenVPN 설정에 속합니다.
nc -vz 127.0.0.1 1194
journalctl -u stunnel -n 50 --no-pager
그 프로브는 백엔드 소켓과 래퍼 로그를 덮으며, 거부된 백엔드와 거부된 핸드셰이크를 구분합니다. 사후가 아니라 한 번의 시도가 진행되는 동안 실행하십시오. 한 번의 시도에서 나온 타임스탬프가 비교를 신뢰할 수 있게 합니다.
두 신원, 두 실패 순서
바깥 인증서는 래퍼에, 안쪽 신원은 OpenVPN에 속하며 서로 다른 기관에서 올 수 있습니다. 경로를 건강해 보이게 하려고 둘 중 하나의 검사를 끄는 것은 실제 보호를 겉모습과 맞바꾸는 일입니다. 메시지 순서가 계층을 알려 주는데, 래퍼 인증서 문제는 어떤 VPN 옵션이 협상되기 전에 나타나고 안쪽 신원 실패는 스트림이 확립된 뒤에야 나타나므로, 두 검증을 모두 유지하고 순서대로 디버그하십시오.
stunnel 설명서 accept, connect, 클라이언트 모드를 정확히 정의하며, 그 절은 추측보다 빨리 소켓 질문에 답합니다. 어느 계층이 응답했는지 아직 모르겠다면, 아래 명령으로 공개 포트가 제시하는 인증서를 읽으십시오. 출력에 래퍼 인증서가 있으면 전달이 래퍼에 도달한 것이고, 침묵이나 프로토콜 오류라면 도달하지 않은 것입니다. 그 한 가지 구분이 여기서 다른 어떤 확인보다 많은 시간을 아껴 줍니다.
openssl s_client -connect vpn.example:443 -servername vpn.example </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer