macvlan 컨테이너가 VPN 클라이언트에 응답할 수 없는 이유
macvlan 컨테이너는 자체 호스트와 통신할 수 없고 응답이 잘못된 게이트웨이로 나갈 수 있습니다. 호스트 쪽에 shim 경로를 추가한 다음 소스 모델을 선택하십시오.
VPN을 종료하면서 동시에 macvlan 네트워크에서 컨테이너를 실행하는 Linux 호스트를 상상해 보십시오. LAN은 192.168.60.0/24이고, 컨테이너는 192.168.60.210을 가지며, VPN 클라이언트는 10.95.0.0/24에서 옵니다. 클라이언트는 서비스에 도달하지만 응답은 결코 돌아오지 않고, 호스트의 모든 방화벽 규칙은 올바르게 보입니다. 이 증상을 만드는 제약은 두 가지이며, 하나를 고쳐도 다른 하나는 그대로 남습니다.
두 가지 제약, 하나의 증상
첫 번째 제약은 격리이며, Docker의 macvlan 드라이버는 컨테이너가 상위 인터페이스를 통해 자체 호스트와 통신하도록 허용하지 않습니다. 호스트 스택과 컨테이너 사이의 트래픽에는 경로가 없으며, 호스트의 경로를 어떻게 작성하더라도 마찬가지입니다.
두 번째 제약은 반환 경로입니다. 컨테이너의 기본 게이트웨이는 보통 LAN 라우터이므로 VPN 클라이언트로 향하는 응답은 그 라우터를 통해 나갑니다. 라우터에 VPN 풀로 돌아가는 경로가 없으면 응답은 중간 어딘가에서 버려집니다.
두 실패는 클라이언트 입장에서 요청은 도착하지만 응답은 결코 오지 않는 동일한 모습으로 보입니다. 둘은 서로 다른 수리가 필요하며, 넓은 masquerade 규칙은 어느 쪽이 아직 고장 났는지를 숨길 수 있습니다. 그래서 첫 번째 테스트는 방화벽을 또 바꾸는 것이 아니라 컨테이너 쪽에서의 패킷 캡처입니다. 요청이 그곳에 전혀 나타나지 않는다면 격리 제약이 작동 중입니다.
호스트 쪽 shim을 좁게 만드십시오
같은 상위에 브리지 모드로 연결된 두 번째 macvlan 인터페이스는 호스트 스택에 해당 LAN 세그먼트에서 고유한 식별자를 부여합니다. DHCP 풀 밖이면서 컨테이너 범위 밖의 주소를 그것을 위해 예약하고, 컨테이너만 그 경로로 보내십시오.
ip link add macvlan-vpn link eth0 type macvlan mode bridge ip address add 192.168.60.250/32 dev macvlan-vpn ip link set macvlan-vpn up ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250
첫 번째 명령은 인터페이스를 브리지 모드로 만드는데, 이는 이 드라이버의 문서화된 기본값이며 호스트와 컨테이너 사이 트래픽에 원하는 모드입니다. 두 번째는 주소가 LAN 접두사와 충돌하지 않도록 /32를 할당하고, 네 번째는 shim을 통해 컨테이너의 주소만 보냅니다.
새 인터페이스로 LAN 전체를 돌리지 마십시오. 일반 연결 경로는 그대로 두고, 호스트 경로는 의도적으로 좁게 유지하여 컨테이너 하나가 경로를 얻되 세그먼트의 나머지는 동작을 바꾸지 않도록 합니다. shim을 가리키는 기본 경로는 다른 결과를 낳는 다른 설계가 됩니다. 구체적으로 유지하면 피해 범위는 작게 남습니다.
이 명령들은 실행 중인 호스트의 네트워크 설정을 바꿉니다. 대화형 root 셸 변경은 업그레이드 후에도 남지 않을 수 있으므로, 어플라이언스나 관리형 플랫폼에서는 해당 플랫폼이 지원하는 구성 방식을 사용하십시오.
소스를 어떻게 보존할지 결정하십시오
shim이 있으면 컨테이너가 호스트에 도달할 수 있고, 질문은 응답이 어떤 소스 주소를 실어 나르는가가 됩니다. 원래 VPN 소스를 보존하는 것이 더 깔끔한 모델이며, 컨테이너는 실제 클라이언트 주소를 보고 서비스의 로그와 접근 규칙이 그것을 사용할 수 있습니다.
그것이 작동하려면 컨테이너의 네트워크 구성이 이 경로에 대해 10.95.0.0/24의 트래픽을 192.168.60.250으로 게이트웨이로 보내야 합니다. 이는 컨테이너 자체 구성 안의 지원되는 경로 또는 게이트웨이 설정이며, 호스트 쪽 요령이 아닙니다. 설정이 적용되었다고 가정하지 말고 컨테이너 안에서 확인하십시오. 여전히 LAN 라우터를 가리키는 기본 게이트웨이는 응답을 같은 구멍으로 계속 보냅니다.
승인된 설계가 대신 VPN 소스를 숨긴다면 번역 범위를 실제 VPN 풀, 나가는 인터페이스로서의 shim, 특정 컨테이너와 서비스로 좁히십시오.
iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250
shim을 이그레스 인터페이스로 맞추고 터널로 맞추지 마십시오. 터널을 나가는 인터페이스로 지목하는 규칙은 컨테이너로 향하는 패킷과 일치하지 않으며, 이것이 이런 구성에 흔히 있는 실수입니다. 규칙은 위 문장만큼 좁게 유지하고 풀이 바뀌면 다시 검토하십시오.
호스트가 아니라 클라이언트에서 검증하십시오
호스트 자체에서 shim 주소에 바인딩한 요청은 shim이 컨테이너에 도달할 수 있음을 증명합니다. 그러나 그 테스트의 소스 주소가 shim 자체의 것이므로 보존된 10.95.0.x 소스로 트래픽을 되돌릴 수 있음을 증명하지는 않습니다.
curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210첫 번째 명령은 호스트에서 컨테이너까지의 구간을 시험하고, 두 번째는 실제 VPN 클라이언트가 요청하는 동안 shim을 실제로 무엇이 통과하는지 보여 줍니다. 들어오는 경로의 소스 주소와 같은 흐름으로 응답이 나타나는지 보십시오.
호스트에서 전달이 활성화되어 있어야 하고, 전달 경로에는 서비스 포트에서 VPN 풀에서 shim으로 가는 허용과 설정된 응답에 대한 허용이 필요합니다. 호스트의 INPUT 규칙은 전달되는 트래픽을 승인하지 않으며, 라우팅이 올바르게 보인 뒤 패킷이 버려지는 흔한 이유입니다.
실제 애플리케이션을 실제 자격 증명으로 실행한 다음, 같은 컨테이너의 무관한 두 번째 서비스가 여전히 거부하는지 확인하십시오. 작동시키는 유일한 방법이 모든 전달 규칙을 여는 것이었다면 설계는 끝난 것이 아닙니다. 앞으로 그 서비스의 접근 규칙이 사용할 주소이므로 서비스가 어떤 소스 주소를 기록했는지도 확인하십시오.