OpenVPN과 HTTPS 443 포트: 리스너는 누구의 것인가
TCP와 UDP 443은 별개의 소켓입니다. 하나의 TCP 리스너를 공유하려면 소유자가 필요하고, OpenVPN의 포트 공유는 좁은 합의이지 프록시 요령이 아닙니다.
두 서비스가 결코 경쟁하지 않고 둘 다 443 포트에 응답할 수 있는 것은 리스너가 번호만이 아니라 전송, 주소, 포트를 함께 기준으로 정해지기 때문입니다. 한 대의 컴퓨터에 웹 서버와 OpenVPN을 올린다면, 가장 먼저 답할 가치가 있는 질문은 각 프로세스가 커널에 어떤 소켓을 요구하는가입니다. 구성을 편집하기 전에 그 목록을 적어 두면 «주소가 이미 사용 중» 오류의 대부분은 스스로 설명됩니다. 목록 다음의 모든 것은 UDP 리스너, 공유 TCP 소켓, 프로토콜에 따라 라우팅하는 프런트엔드 중 하나를 고르는 일입니다.
각 프로세스가 요구하는 소켓부터 시작하십시오
bind는 그 삼중주에 따라 성공하거나 실패하므로, 두 데몬은 세 부분이 모두 겹칠 때만 충돌합니다. 그래서 TCP 443의 웹사이트가 UDP 443의 OpenVPN 리스너와 무기한 공존하며, 그래서 둘 중 하나를 같은 호스트의 두 번째 로컬 주소로 옮기는 것도 논쟁을 끝냅니다. 살아 있는 리스너를 읽으십시오. 그것을 만들었어야 할 파일이 아니라, 오래된 include나 잊힌 unit 파일이 기억하는 편집보다 오래 살아남기 때문입니다.
| Line in the listener list | What it establishes | What to do next |
|---|---|---|
| One udp row and one tcp row, each on 443 | Separate transport sockets, nothing contested | Point the VPN profile at udp and stop editing |
| A single tcp address and port listed by two processes | A real bind collision between two daemons | Move one service, or put a dispatcher in front of both |
| A proxy process owns the socket, no vpn process | The proxy accepts and has to hand off correctly | Check that its backend speaks the protocol it forwards |
root로 ss -lntup을 실행하고 443을 언급하는 모든 줄을 IPv6 항목까지 읽으십시오. 보통 와일드카드 v6 리스너는 v4 트래픽도 받으며, 그래서 잊고 있던 리스너가 책임이라고 생각한 파일을 바꾼 뒤에도 포트를 계속 차지합니다. 프로세스 이름이 낯설다면 아무것도 건드리기 전에 ss -lntup 'sport = :443'으로 출력을 좁히십시오.
네트워크가 허락하면 터널을 UDP로 바꾸십시오
UDP 리스너는 충돌을 완전히 우회하며 보통 가장 짧은 수리입니다. 소켓을 공유하지 않고 경로에 추가 제품이 들어오지 않기 때문입니다. 하지만 공짜는 아닙니다. 일부 클라이언트 네트워크는 reset을 보내지 않고 UDP 443을 버리므로, 터널이 bind에서 실패하는 대신 설정을 멈추고, 사용자는 읽을 오류도 없이 VPN이 죽었다고 보고합니다. UDP 리스너는 웹 계층 재시작도 견디므로 사이트를 자주 다시 배포하는 컴퓨터에서 유효합니다. 사용자가 있는 네트워크에서 시험하십시오. 서버의 셸은 서버가 자기 자신에게 닿는다는 것만 증명합니다.
서버 구성과 클라이언트 프로필에서 전송을 함께 바꾸십시오. 여전히 TCP를 요구하는 프로필은 UDP만 있는 리스너를 상대로 재연결을 반복하며, 두 파일을 비교하기 전까지는 네트워크 장애처럼 보입니다.
VPN 프로세스가 TCP 443을 소유하게 하고 나머지는 전달하십시오
TCP 서버 모드의 Community OpenVPN은 들어오는 연결의 첫 바이트를 읽고 자기 프로토콜이 아닌 모든 것을 HTTPS 백엔드로 전달합니다. port-share 지시문이 바로 그 용도입니다. 백엔드는 TLS가 켜진 평범한 웹 서버이며, 그 지시문에서는 URL이 아니라 호스트와 포트로 이름이 붙습니다.
port-share 10.0.0.5 8080
사이트가 두 번째 사설 주소를 가진 컴퓨터에서는 그 줄이 VPN이 아닌 트래픽을 10.0.0.5:8080으로 보내므로, HTTPS 가상 호스트가 그곳에 바인딩되어야 하고 방화벽이 로컬 홉을 허용해야 합니다. 웹 서버가 TLS를 직접 종료해야 합니다. 도착하는 바이트가 브라우저의 원래 핸드셰이크이고 그 사이에서 아무것도 복호화하지 않았기 때문입니다. 지시문을 평범한 HTTP 리스너로 향하게 하면 브라우저는 잘못된 메서드 오류를 받는데, 이는 백엔드가 잘못 놓인 것이 아니라 깨진 사이트처럼 읽힙니다. 지시문은 TCP 서버 모드에만 있고, UDP 리스너에는 검사할 스트림이 없습니다.
VPN 프로세스가 모든 연결을 받으므로, 웹 애플리케이션은 전달된 요청이 방문자가 아니라 호스트 자신의 주소 중 하나에서 오는 것을 봅니다. 실제 클라이언트 주소가 필요한 모든 것은 백엔드의 PROXY 프로토콜 지원이나 그것을 추가하는 프런트엔드에 달려 있습니다. 백엔드를 다른 로컬 주소로 옮겨도 방문자의 주소가 돌아오지 않으며, 사이트가 기록하는 호스트 주소가 바뀔 뿐입니다. 분석 보고서가 질문을 제기하기 전에 그 제약을 배포 노트에 적으십시오.
리버스 프록시는 잘못된 도구이고, 전송 계층 라우터는 그렇지 않습니다
HTTP 리버스 프록시는 요청을 읽기 위해 TLS를 종료하므로 OpenVPN 스트림을 그대로 통과시킬 수 없습니다. SNI나 첫 패킷 검사로 전달하는 전송 계층 라우터는 VPN이 의존하는 세션을 끝내지 않는 한 둘 모두 앞에 설 수 있습니다. 두 장치는 도면에서는 비슷해 보이지만 소켓에서는 전혀 다르게 행동합니다.
상용 Access Server는 자체 포트 공유 설정을 제공하며, 그것은 커뮤니티 지시문과 일대일로 대응하지 않습니다. 다른 쪽을 위해 쓰인 안내서를 적용하기 전에 제품과 버전을 확인하십시오. 조용히 무시되는 복사된 설정은 설정이 없는 것보다 나쁩니다. 그 뒤에도 리스너 목록은 그럴듯해 보이기 때문입니다.
웹사이트와 터널을 두 개의 별도 경로로 시험하십시오
사이트를 열고 터널을 연결한 다음, 리스너 목록을 다시 읽어 지금 443을 누가 소유하는지 보십시오. 열리는 페이지는 VPN에 대해 아무것도 증명하지 않고, 연결되는 터널은 사이트에 대해 아무것도 증명하지 않습니다. 둘 다 같은 번호를 쓰더라도 마찬가지입니다. 아래 세 명령은 공유 소켓, 웹 경로, VPN 서비스를 그 순서로 확인합니다.
ss -lntup 'sport = :443' curl -sI https://vpn.example.com/ | head -n 1 journalctl -u openvpn-server@server -n 20
같은 순간에 대해 백엔드 접근 로그의 클라이언트 주소와 VPN 로그의 주소를 비교하십시오. 사이트가 모든 방문자를 호스트 자신으로 기록하면 전달은 동작하고 주소 처리는 동작하지 않습니다. 두 로그가 모두 조용하면 프런트엔드가 연결을 넘기지 않은 것입니다. 어느 쪽이든 소켓을 누가 받는지는 리스너 목록이 결정하며, 다른 파일을 바꾸기 전에 확인해야 할 사실이 바로 그것입니다.
그 리스너 지도를 구성 옆에 두어 443을 만지는 다음 사람이 어느 프로세스가 받고 다른 프로토콜이 어디로 갔는지 알게 하십시오. 편집이 무엇을 하려 했는지 믿는 대신 변경 후 소유권을 확인하십시오.