VPN 클라이언트를 다시 시작해도 터널이 돌아왔다는 것만 증명됩니다. 그 터널을 통해 나가라고 지시받은 프록시에 대해서는 아무것도 말하지 않습니다. Squid, tinyproxy 및 대부분의 다른 포워더는 시작할 때 확인한 로컬 소스 주소를, 무언가가 재로드를 강제할 때까지 유지합니다. 재연결이 새 터널 주소를 내주면 포워더는 모든 아웃바운드 연결에서 실패하거나, 평소 경로로 나가기 시작합니다.

위험한 것은 두 번째 실패로, 터널은 살아 있고 페이지도 열리는데 나가는 주소만 잘못된 경우입니다.

터널이 아니라 리스너부터 보세요

주소는 세 개가 관여하고, 재연결은 그중 일부만 움직입니다. 리스너는 브라우저가 가리키는 곳으로 보통 127.0.0.1이나 LAN 주소이며, 터널이 바뀐 것은 상관하지 않습니다. 아웃바운드 로컬 소스는 포워더가 다음 홉을 호출할 때 커널에 사용하라고 요청하는 것이고, 터널 장치에 묶여 있습니다. 공인 출구는 웹 서버가 기록하는 것으로, 몇 홉 떨어진 변환된 주소일 수 있습니다.

공인 IP 조회는 마지막 질문에만 답하는데, 하나의 공인 출구가 여러 내부 소스를 숨길 수 있으므로 포워더가 어느 로컬 주소에 묶여야 하는지는 알려 주지 못합니다. 주소는 연결을 소유한 쪽에서 읽으세요. 클라이언트의 상태 출력, 인터페이스 자체, 또는 터널이 사는 네임스페이스입니다. 이름이 터널처럼 보이는 첫 인터페이스를 잡으면 두 번째 프로필이 있는 순간 잘못된 답이 됩니다.

컨테이너와 네임스페이스 구성은 이 가정을 조용히 깨뜨립니다. 한 네트워크 네임스페이스의 포워더는 다른 곳에 있는 터널에 묶일 수 없고, 구성을 아무리 편집해도 고쳐지지 않습니다.

무엇이든 편집하기 전 네 가지 점검

순서대로 진행하세요. 처음 실패한 점검이 멈출 지점인데, 뒤의 점검이 앞의 점검이 성립한다고 가정하기 때문입니다.

  1. 사용 중인 터널이 프록시를 만든 기준 프로필인지, 스스로 연결된 두 번째 프로필이 아닌지 확인합니다.
  2. 해당 장치에 현재 있는 주소를 출력하고 실행 중인 구성의 주소와 비교합니다.
  3. 디스크의 파일이 주장하는 것이 아니라 포워더가 실제로 확인한 소스를 물어봅니다.
  4. 포워더의 트래픽이 정말로 예상하는 라우팅 및 방화벽 정책을 따르는지 확인합니다.

장치 주소는 간단한데, ip -4 addr show dev tun0 가 현재 주소를 출력하고 ip -4 route get 1.1.1.1 가 그 목적지에 대해 커널이 어느 인터페이스를 고를지 보여 줍니다. 정확한 주소에 묶는 포워더는 주소가 사라질 때 크게 실패합니다. 장치에 묶거나 기본 소스로 되돌아가는 포워더는 계속 동작하며 누출되고, 이것이 조용한 결과입니다.

문서는 검색 최상단이 아니라 실행하는 릴리스에 맞추세요. Squid의 아웃바운드 주소 지시문은 v7 이전용으로 문서화되어 있고, v8 문서는 그 지시문이 거기서 제공되지 않는다고 분명히 밝히므로, 그것에 기대어 만든 스크립트는 그 경계를 넘지 못합니다(Squid tcp_outgoing_address 참조 참고). 무엇이든 재로드하기 전에 제품 자체의 파서로 검증하세요(squid -k parse 는 오류를 보고하고 실행 중인 프로세스를 건드리지 않고 종료합니다).

각 터널에 번호를 붙이고 오래된 교체를 버리세요

재연결은 인계이고, 인계에는 순서가 필요합니다. 관찰한 각 연결에 성공적으로 수립될 때마다 증가하는 카운터나 타임스탬프 태그를 붙이고, 그 태그를 후보 구성 안에 넣어 전달하세요. 후보의 태그가 현재보다 오래되면 적용하지 말고 후보를 버리세요(이전 터널을 위해 작성된 느린 갱신이 그렇지 않으면 현재 설정을 덮어쓰기 때문입니다). 이벤트 폭주는 하나로 합쳐 흔들리는 링크가 열다섯 번이 아니라 한 번의 전환을 만들게 하세요.

작업을 네 동작으로 나누세요. 이전 이그레스 상태를 무효화하고, 연결 소유자가 완료를 보고할 때까지 기다리고, 관리되는 조각만 만들고, 마지막으로 서비스 관리자를 통해 검증하고 활성화합니다. 주소 값 두 개로 파일 전체를 다시 생성하면 리스너 제한, 인증, 목적지 정책이 조용히 사라집니다. 의도적인 중지도 존중하세요(사용자가 끈 터널에 계속 연결을 시도하는 도우미는 버그이지 복원력이 아닙니다).

열린 소켓은 새 주소를 따르지 않습니다

포워더를 재구성해도 이미 수립된 연결에 대해서는 아무 말도 하지 않습니다. 비워질지 죽을지는 제품에 달려 있으므로 가정하지 말고 동작을 관찰하세요.

교체 전에 열린 소켓으로 처리되는 요청은 새 구성이 올바르더라도 여전히 이전 경로로 나갑니다. 그것이 중요하다면 짧은 배출 기간을 두고 새 작업 수용을 멈추거나, 이전 소켓을 닫고 오류를 받아들일지를 명시적으로 결정하세요. 그런 다음 새 연결로 테스트하고 그 결과를 배출 점검과 분리해 두세요. 소스 바인딩도 보안 경계가 아닙니다. 트래픽이 평소 경로를 절대 건드려서는 안 된다면 표시와 방화벽 규칙으로, DNS와 IPv6까지 포함해 강제하여, 재로드가 실패하면 프록시가 열린 채가 아니라 명시적으로 내려간 상태가 되게 하세요.

새 출구를 새 요청으로 증명하세요

중요한 것은 활성화 후 열린 요청이며, ping도 아니고 이미 캐시된 페이지도 아닙니다. 프록시에 실제 URL을 요청하고 원격 끝이 보고하는 출구 주소를 읽은 다음, 공급자가 보여 줄 때 클라이언트 자신의 터널 관점과 비교하세요.

파싱, 재로드, 요청을 별도 명령으로 유지해 실패가 한 단계를 가리키게 하세요. 처음 둘은 실패해도 아무것도 바꾸지 않으며, 바로 그래서 재시작 전에 실행합니다.

squid -k parse
sudo squid -k reconfigure
curl -x http://127.0.0.1:3128 -sS -o /dev/null -w '%{http_code} %{remote_ip}\n' https://example.com

오래된 출구로 서비스하는 프록시는 짧은 중단보다 나쁘므로, 재로드가 실패하면 서비스를 멈추고 조각을 고치세요. 재로드가 성공했는데 새 요청이 여전히 예상 밖의 곳으로 나간다면, 주소를 다시 편집하지 말고 라우팅 점검으로 돌아가세요. 검증한 터널 세대를 기록해 두면 다음 재연결에서 구체적으로 비교할 것이 생깁니다.

관련 글