어제 맞던 규칙이 오늘은 맞지 않는 것은 클라이언트가 다른 터널 주소로 돌아왔기 때문이다. 그러나 할당기는 무작위가 아니며, 그 순서를 알면 이 놀라움은 예측 가능한 사건이 된다. 같은 클라이언트가 이전에 갖고 있던 주소를 우선하고, 가장 오래 비어 있던 주소로 물러나며, 기억할 곳을 주지 않으면 모든 것을 잊는다. 임대를 전제로 한 규칙은 조용히 맞지 않게 되는 날까지 계속 맞는다.

할당기가 따르는 순서

common name마다 세션이 하나일 때 할당기는 먼저 같은 클라이언트가 이전에 사용했고 지금 비어 있는 주소를 찾는다. 그 주소가 없으면 가장 오래 유휴 상태였던 빈 주소를 가져간다. 같은 이름에 동시 세션이 켜져 있으면 이전 주소 우선은 적용되지 않고 대신 첫 번째 빈 주소가 쓰이는 것은 세션을 서로 별개의 대등한 노드로 보기 때문이다.

SituationAddress chosenPractical effect
Reconnect, old address still freeThe remembered addressRules appear stable for days
Old address taken by another clientLeast recently used free addressA working rule silently stops matching
Concurrent sessions, same nameFirst free address, per sessionOne identity can hold several leases

여기서 두 가지 결과가 곧바로 나온다. 빨리 다시 접속하는 클라이언트는 보통 자기 주소를 유지하므로, 그것이 바뀌기 전까지 아무도 이 구조를 알아차리지 못한다. 그리고 그 짧은 창에 접속한 다른 기기가 주소가 잠시 비어 있는 사이에 가져갈 수 있고, 그러면 첫 클라이언트는 다른 것을 받으며 옛 번호에 묶인 모든 규칙이 틀린다. 두 사건 모두 장애처럼 보이는 로그 줄을 남기지 않는다.

임대가 안정적으로 보이다가 움직이는 이유

여기서의 안정성은 다른 누군가 주소를 요구하기 전에 재접속이 도착한다는 창발적 성질이다. 약속이 아니며 클라이언트가 끊긴 동안에는 보장되지 않는다. 놀라기보다 주소가 바뀐다고 계획하라. 기기 수보다 겨우 큰 풀은 충돌을 일상으로 만들며, 가장 오래 사용되지 않은 주소로 물러날 때 고를 것이 거의 없다.

최대 동시 접속 수가 크기를 정하는 숫자이며 이용자 수가 아니다. 동시에 두 기기에서 시험하는 사람이나, 옛 세션이 끝나기 전에 다시 접속하는 클라이언트는 한동안 임대 두 개를 차지한다. 사람 수만으로 설계한 풀은 사람들이 서버 탓으로 돌리는 바로 그 교체를 만들어 낸다.

지속 파일은 기억만 하고 예약하지 않는다

서비스 재시작을 넘겨 살아남는 주소에는 지속 파일이 필요하다. 종료할 때 클라이언트 이름과 주소를 저장하고 서비스가 시작될 때 다시 읽으므로, 계획된 재시작이 더 이상 작성한 모든 규칙을 뒤섞지 않는다.

ifconfig-pool-persist /etc/openvpn/ipp.txt
server 10.8.0.0 255.255.255.0

그것이 하지 않는 일은 클라이언트가 없는 동안 주소를 붙들고 있는 것이다. 그 틈에 할당기는 번호를 다른 사람에게 줄 수 있고, 파일에는 다음 연결이 지킬 수 없는 낡은 선호가 기록된다. 재시작 동작을 개선하는 힌트로 다루고, 고정 주소로 여기지 말아야 한다.

파일을 보는 김에 풀을 라우팅된 각 서브넷과 맞춰 확인하라. 겹치는 범위는 서버가 라우팅할 수 없는 주소를 내주며, 증상은 접속하고 주소를 받았는데 아무것도 닿지 못하는 클라이언트다.

주소를 올바르게 고정하기

방화벽 규칙이나 DNS 레코드가 정말 고정 주소를 필요로 한다면 기대하지 말고 할당하라. 클라이언트별 설정 항목은 주소와 마스크를 직접 밀어 넣을 수 있고, 그 항목은 실제 클라이언트 이름을 키로 삼는다.

# client-config-dir entry for "laptop-acme"
ifconfig-push 10.8.0.50 255.255.255.0

고정 주소는 동적 풀 밖에 두어 할당기가 같은 번호를 다른 세션에 주지 않게 한다. 그다음 각 클라이언트가 소비하는 풀 주소 수가 달라지므로 터널 구조를 확인하라: 옛 지점 간 배치는 클라이언트마다 작은 블록을 소비한다반면 서브넷 배치는 하나씩 한 주소만 쓴다. 한 구조에서 넉넉해 보이는 풀이 다른 구조에서는 고갈될 수 있다.

서버의 장부를 믿지 말고 클라이언트에서 결과를 확인하라. 세션이 돌아오면 인터페이스 주소와 밀어 넣은 경로를 보는 것은, 서버 로그가 요청된 주소를 알릴 수 있지만 인터페이스 자체는 다른 주소를 갖고 있을 수 있기 때문이다.

원격 주소는 별개의 문제다

클라이언트의 remote 줄에 있는 주소는 어떤 터널이 생기기 전에 닿을 수 있어야 한다. 풀 주소, 예컨대 서버 자신의 터널 종점을 거기에 두면 클라이언트는 아직 세우지 않은 터널을 통해 종점에 닿으려 하고, 결과는 지름길이 아니라 루프나 조용한 시간 초과다.

운영자가 제공한 공용 종점을 쓰고, 풀은 원래 용도인 터널 내부 주소에 남겨 두어라. 풀 범위와 고정 할당, 지속 경로를 한곳에 적어 두면 다음 사람이 모든 임대를 임의로 여기지 않게 된다.

관련 글