Docker의 OpenVPN이 /dev/net/tun을 열지 못할 때: 무엇이 빠졌는가
TUN 노드와 네트워크 권한은 별개의 두 허가입니다. 둘 다 열고 나서 같은 수정을 반복하는 대신 다음 오류를 그 자체의 조건으로 읽으십시오.
컨테이너 이미지는 필요한 모든 OpenVPN 바이너리와 구성 파일을 담고도 첫 네트워크 호출에서 실패할 수 있습니다. 오류가 /dev/net/tun을 언급하는 것은 애플리케이션이 커널에 TUN 인터페이스를 요청했지만 컨테이너에 장치 노드도, 그것을 만들 권한도 없었기 때문입니다. 이 둘은 별개의 허가이며, 하나를 고쳐도 다른 하나는 있던 자리에 그대로 남습니다.
둘을 분리하려면 각각 한 개의 명령이 필요합니다. 그다음 오류 메시지가 실제로 어느 경계에 서 있었는지 알려 줍니다.
장치 노드와 권한은 두 개의 문
장치 노드는 파일 시스템 객체이므로 컨테이너는 자신의 마운트 네임스페이스에서 그것을 보아야 합니다. 권한은 허가이므로 프로세스는 인터페이스가 만들어질 네임스페이스에서 CAP_NET_ADMIN이 필요합니다. 권한 없이 장치를 넘기면 열리는 노드와 실패하는 ioctl을 얻게 됩니다. 장치 없이 권한을 주면 애플리케이션이 아무것도 열 수 없게 되므로, 예제에서는 보통 둘이 함께 등장합니다.
Docker의 devices 설정은 호스트 장치를 컨테이너 안으로 매핑하고, cap_add는 권한 집합을 조정합니다. 같은 경로의 bind mount는 장치 접근 의미론을 적용하지 않고 파일을 시야에 넣습니다.
Compose 파일 밖에서 재현하십시오
서비스를 편집하기 전에 호스트에 장치가 있는지, 그리고 꾸밈없는 컨테이너가 인터페이스를 만들 수 있는지 확인하십시오. 아래 명령은 의도적으로 최소이며, 유일한 목적은 호스트 문제와 compose 문제를 분리하는 것입니다. 이것이 실패하면 어떤 compose 변경도 도움이 되지 않습니다.
ls -l /dev/net/tun
docker run --rm --cap-add NET_ADMIN --device /dev/net/tun:/dev/net/tun alpine sh -c 'apk add -q iproute2 && ip tuntap add dev tun9 mode tun && ip link show tun9'
호스트에 노드가 없으면 tun 모듈을 사용할 수 없다는 뜻이며, 이는 컨테이너가 아니라 호스트 측 수정입니다. 노드가 있는데도 컨테이너 안에서 열리지 않으면 장치 접근을 가리키며, 메시지는 no such file이 아니라 permission denied라고 말합니다. 이 두 실패의 순서가 진단의 전부입니다. 플래그를 바꾸기 전에 어느 것을 보았는지 적어 두십시오.
TUN 이후의 오류는 다른 문제입니다
인터페이스가 나타나면 다음 실패는 다른 주인을 가집니다. 인증 오류는 터널이 서버에 도달했고 자격 증명이 거부되었다는 뜻이므로 권한 변경은 도움이 되지 않습니다. 애플리케이션이 여전히 실패하는데 터널이 설정되면 경로, 전달, 컨테이너 내부의 DNS 확인 또는 컨테이너 자체의 네트워크 배치를 가리킵니다. 그중 어느 것도 TUN 권한으로는 답할 수 없는 평범한 네트워크 질문입니다. 변경할 때마다 원래 테스트를 반복하면 실패가 하나의 인상으로 합쳐지는 것을 막습니다.
작동하는 예제에서 모든 설정을 복사하는 것이 최소 수정을 읽을 수 없는 서비스 정의로 만드는 길입니다. 이 배포에 필요한 것만 가져오고 각각이 왜 있는지 기록하십시오.
컨테이너 안에서 인터페이스를 검증하십시오
인터페이스와 권한 집합을 호스트가 아니라 실행 중인 컨테이너 내부에서 확인하십시오. 아래 명령은 장치 노드, 권한 목록, 그리고 인터페이스를 만들 수 있는지 자체를 보여 줍니다. 클라이언트를 실행하는 같은 컨테이너에서 실행하고, 이미지가 최소라면 도구를 설치하십시오.
ls -l /dev/net/tun
capsh --print | grep -i net_admin
ip link add dev tun9 type tun && ip link show tun9
bounding set에 있지만 effective set에 없는 권한은 한 번도 주어지지 않은 권한과 다르게 동작하며, capsh는 둘 다 보여 줍니다. 노드가 있고 권한도 있는데 생성이 계속 실패한다면 런타임이 seccomp 프로필이나 AppArmor 정책처럼 작업을 제한하는 다른 무언가를 적용하고 있는 것입니다. 그것은 애플리케이션이 아니라 런타임이 문서화하는 세 번째 경계입니다.
컨테이너 플래그, 이미지, 그리고 각 시도의 정확한 오류를 기록하십시오. 그 메모를 다음에 읽는 사람은 전체 조사를 반복하지 않고 어느 문이 닫혀 있었는지 알 수 있습니다.