Android OpenVPN은 터널 주소 없이 경로를 추가하지 않습니다
Android OpenVPN 클라이언트는 휴대전화에 터널 주소가 생기기 전까지 경로를 추가할 수 없습니다. 누가 주소를 할당하는지, 어떤 pull 필터가 주소를 버리는지, 언제 직접 입력해야 하는지 확인하십시오.
Android의 OpenVPN 프로필이 경로를 추가하지 못하는 이유는 휴대전화가 가상 인터페이스에 주소를 가지고 있지 않아 경로가 가리킬 대상이 없기 때문입니다. 경로는 패킷이 어디로 가야 하는지만 답합니다. 터널 주소는 터널 안에서 휴대전화가 누구인지를 답하며, 인터페이스가 존재하려면 클라이언트가 먼저 하나를 제공해야 합니다. 아래 네 가지 점검을 순서대로 수행하고 첫 실패에서 멈추십시오. 주소가 생기기 전에 경로를 편집하면 진짜 문제가 가려집니다.
클라이언트가 실행하는 순서대로 실패를 읽으십시오
Android의 VpnService.Builder는 두 개념을 분리합니다. addAddress()는 앱이 만드는 인터페이스에 주소를 올리고, addRoute()는 목적지 프리픽스를 더하며, establish()는 적어도 하나의 주소가 추가되기 전에는 인터페이스 생성을 거부합니다. OpenVPN 클라이언트는 프로필과 서버가 푸시한 옵션을 정확히 그 호출들에 매핑하므로, 주소를 한 번도 해석하지 않는 연결은 인터페이스를 아예 만들 수 없습니다.
읽고 있는 로그 줄이 경로를 언급하는데 원인이 한 단계 앞에 있는 이유가 이것입니다. 클라이언트는 인터페이스가 생긴 뒤에야 경로 단계에 도달하며, 주소가 없으면 경로 호출은 즉시 실패하거나 전혀 실행되지 않습니다. 로그가 경로를 추가할 수 없다고 하면 경로 문법이 아니라 주소부터 확인하십시오.
점검 1: 서버가 응답에 주소를 넣는가
라우팅되는 OpenVPN 서비스에서 주소는 서버 풀 또는 클라이언트별 할당에서 오며, 그 형태는 토폴로지가 결정합니다. OpenVPN 2.4 이상 서버에서 서브넷 토폴로지 서비스는 다음과 같습니다.
topology subnet
server 10.8.0.0 255.255.255.0
client-config-dir ccd
이 형태라면 서버는 ifconfig 10.8.0.6 255.255.255.0 같은 것을 푸시합니다. 더 오래된 topology net30 구성은 대신 피어 주소, 예를 들어 ifconfig 10.8.0.6 10.8.0.5를 푸시하므로, 두 모델 사이를 옮긴 프로필은 올바르게 보이면서도 잘못된 넷마스크를 지닐 수 있습니다.
클라이언트 연결 로그에서 푸시된 옵션 집합을 찾으십시오. ifconfig 줄이 전혀 없다면 서버가 주소를 보낸 적이 없거나 클라이언트가 그 옵션을 거부한 것입니다. client-config-dir를 쓰는 서버에서는 인증서의 common name 이름을 딴 파일이 존재하고 할당을 담고 있어야 합니다.
# ccd/phone-anna
ifconfig-push 10.8.0.6 255.255.255.0
점검 2: 클라이언트가 받은 주소를 유지하는가
너무 넓은 필터가 두 번째 흔한 원인입니다. pull-filter는 OpenVPN 2.4 이상에 있으며, 여러 필터가 같은 옵션과 일치하면 마지막으로 일치한 것이 이기므로 끝에 둔 catch-all은 오류 없이 주소를 지웁니다.
# removes every pushed option, including the address
pull-filter ignore "ifconfig"
pull-filter ignore "route"
필터를 정말 없애려는 옵션까지만 좁히고 주소는 건드리지 마십시오.
# keeps the pushed address, drops one unwanted LAN route
pull-filter ignore "route 10.60.0.0"
모든 pull을 끄라는 조언은 보통 경로 하나만 없애고 싶은 사람에게서 나옵니다. route-nopull는 더 좁은 스위치로, ifconfig와 나머지 푸시 옵션은 유지하면서 푸시된 경로와 DHCP식 옵션은 거부합니다. 정말 그것이 원할 때만 쓰고, 주소 문제는 따로 다루십시오.
점검 3: 그 주소는 직접 입력해도 되는 것인가
수동 주소 지정은 운영자가 값을 건네줄 때만 정당합니다. 직접 입력한다면 VPN 클라이언트 서브넷에서 와야 하고, 활성 세션 가운데 유일해야 하며, 서버가 쓰는 토폴로지와 맞아야 합니다. 데스크톱 브리지나 원격 LAN의 호스트 주소를 복사하는 것은 두 가지 모두에서 틀립니다. 휴대전화가 이미 다른 곳에 존재하는 주소를 주장하게 되고, 게이트웨이는 그 주소로 돌아갈 경로를 갖지 못합니다.
경로에 적는 원격 LAN 프리픽스는 목적지이며 휴대전화의 정체성이 아닙니다. 10.60.0.0/24에 대한 경로는 그 네트워크에 터널로 도달하라는 뜻이고, 휴대전화가 어느 10.60.0.x 주소를 가져야 하는지는 말하지 않으며, 휴대전화는 그중 어느 것도 가지면 안 됩니다. 고정 할당은 동적 풀과 충돌할 수 없는 서버 쪽에 속합니다.
하나의 정체성에 두 세션이 붙으면 같은 충돌이 드러납니다. 같은 인증서로 두 번 연결하고 서버가 둘 모두에 하나의 고정 주소를 푸시하면 두 번째 세션이 첫 번째를 복제합니다. 해결책은 클라이언트 쪽 편집이 아니라 정체성이나 할당을 나누는 것입니다.
점검 4: 다른 무엇이 터널 자리를 차지하고 있는가
Android는 한 번에 하나의 활성 VPN 서비스만 허용합니다. 다른 VPN 앱이나, 더는 동작하지 않는 프로필에 대해 켜 둔 상시 연결 VPN 항목이 OpenVPN 클라이언트가 establish()를 호출하기 전에 그 자리를 차지할 수 있습니다. 그러면 프로필이 유효해도 인터페이스가 나타나지 않으므로, 프로필을 건드리기 전에 다른 VPN을 끊고 상시 연결 설정을 끈 뒤 다시 연결하십시오.
이더넷 브리징을 고집하는 서비스도 막다른 길입니다. 루트 없는 Android 앱은 IP 터널을 만들 수 있을 뿐 브리지된 이더넷 세그먼트는 만들 수 없으므로, 어떤 주소를 입력해도 dev tap 서버는 동작하지 않습니다. 운영자가 라우팅되는 서비스를 제공해야 합니다. 문제를 보고할 때는 클라이언트 이름과 버전, 푸시된 옵션 집합, 토폴로지, 그리고 주소가 나타났어야 할 정확한 단계를 포함하십시오.
네 점검이 모두 통과하고 주소가 존재하며 유일하고 올바르게 마스크되었다면 경로 문제는 평범한 것이 됩니다. 서버가 어떤 프리픽스를 허용하며 클라이언트가 어떻게 범위를 정해야 하는가입니다. 다른 것을 바꾸기 전에 터널 주소, 넷마스크, 토폴로지를 적어 두십시오. 운영자가 서버 쪽 모습과 대조해야 하는 값이 바로 이 셋이기 때문입니다.