Linux에서 Transmission: 프로세스 소유자별로 나가는 트래픽 강제하기
피어 포트만으로는 충분하지 않다. 방화벽 규칙을 클라이언트 계정으로 좁히고, 두 주소 체계를 모두 덮고, 터널이 내려간 상태에서 시험하라.
Transmission의 들어오는 포트를 막는 것은 VPN 정책이 아니다. 토렌트 클라이언트는 피어와 트래커로 나가는 연결을 열고, 이름을 해석하며, 원격 제어용 리스너를 노출할 수 있다. 그리고 그 각각은 의도하지 않은 인터페이스로 빠져나갈 수 있다. 다섯 가지 점검을 순서대로 수행하고, 경계는 클라이언트 설정이 아니라 방화벽 규칙이라고 보라. 마지막 두 점검이 사람들이 흔히 건너뛰는 것이며, 터널이 끊겼을 때 보장이 유지되는지를 결정하는 것도 이 둘이다.
전송을 소유한 프로세스를 특정하라
데스크톱 앱과 시스템 데몬은 서로 다른 계정으로 실행되며, 소유자 기반 규칙은 프로그램 이름이 아니라 계정을 따른다. 어떤 규칙이든 쓰기 전에 둘 중 무엇이 실행 중인지 확인하라. 전용 서비스 계정은 정책에 정확한 주체를 주지만, 데스크톱 사용자는 브라우저와 편집기, 세션의 다른 모든 것과 신원을 공유한다. 패키지의 계정 이름이 쓰이고 있다고 가정하지 말고 UID를 확인하라.
systemctl status transmission-daemon
ps -o user=,pid=,cmd= -C transmission-daemon
계정이 아직 없다면 이 목적을 위해 만들고, 다른 것은 아무것도 실행하지 않게 하라. 계정과 UID를 규칙 주석에 적어 두라. 주체 없는 규칙은 아무도 안전하게 고칠 수 없는 규칙이기 때문이다.
수신 필드와 경로를 분리하라
Transmission 4.x는 피어 수신 주소를 rpc-bind-address 설정과 별도로 문서화하며, 이 차이는 중요하다. RPC 설정은 원격 제어 리스너만 제어하므로, 그것을 바꾸는 것으로 피어 트래픽의 경로가 선택되지는 않는다. 두 설정을 하나로 읽는 것이, 겉보기에 신중한 구성이 여전히 새는 가장 흔한 이유다. 같은 문서는 피어 수신 주소가 유효하지 않을 때의 대체 동작도 설명한다. 즉 사용할 수 없는 주소는 문서화된 대체 사례이지, 보장된 거부가 아니다.
grep -E '"(peer-port|rpc-bind-address|bind-address-ipv4)"' /var/lib/transmission-daemon/.config/transmission-daemon/settings.json
클라이언트의 제어 항목은 본래 용도로 쓰고, 보장은 방화벽에 두라. 수신 설정도 여전히 쓸모가 있을 수 있지만, 트래커 접촉과 로컬 검색, 위임된 조회가 모두 터널로 나간다는 것을 증명하지는 않는다. 둘이 어긋날 때 결정하는 것은 방화벽이다.
소유자 일치를 올바른 체인에 쓰라
Netfilter의 소유자 일치 설명서는 로컬에서 생성된 패킷이 소켓 파일의 소유 사용자나 그룹에 어떻게 귀속되는지 설명한다. 그 귀속은 전달되는 트래픽에는 미치지 않으며, 보조 그룹 일치에는 명시적 옵션이 필요하다. 실제로 쓰는 확장의 설명서를 읽고, 우연히 찾은 첫 예제를 따르지 말라.
iptables -A OUTPUT -m owner --uid-owner transmission -o tun0 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner transmission -j REJECT
ip6tables -A OUTPUT -m owner --uid-owner transmission -o tun0 -j ACCEPT
ip6tables -A OUTPUT -m owner --uid-owner transmission -j REJECT
순서는 일치만큼 중요하다. 체인 앞쪽의 넓은 허용은 뒤쪽의 정밀한 거부를 무력화한다. 그러니 규칙을 덧붙이고 기대하지 말고 체인 전체를 다시 보라. 호스트가 IPv6를 돌린다면 두 주소 체계를 모두 넣어라. v4만 다루는 정책은 아무도 지켜보지 않는 길을 열어 둔다. 클라이언트와 터널의 재시작을 넘겨서도 규칙을 설치된 상태로 유지하라.
tun0이 사라질 때 무슨 일이 일어나는지 정하라
실패 정책이 이 연습의 핵심이다. 터널이 사라지고 같은 훅이 규칙까지 지운다면, 클라이언트는 다른 무언가가 막을 때까지 물리 인터페이스를 쓸 수 있다. 안전한 설계는 규칙을 남기고 거부하게 둔다. 경계를 터널의 건강과 무관하게 만드는 것이 바로 이것이다. 규칙까지 지우는 해제 훅은 실패 정책의 정반대다.
ip link show tun0
iptables -S OUTPUT
의도적으로 시험하라. 터널을 멈추고, 버려도 안전한 전송을 시작하고, 무언가 나가는지 지켜보라. 그런 다음 터널을 되돌리고 의도한 경로가 다시 동작하는지 확인하라.
규칙이 보지 못하는 경로까지 덮어라
이름 해석은 별도 리졸버 프로세스가 맡을 수 있고, 이름 공간이나 전용 게이트웨이도 그 공유와 부트스트랩 경로가 그렇게 설계되었다면 또 하나의 경계가 될 수 있다. DNS를 어느 구성 요소가 소유하며 같은 출구 규칙을 따르는지 정하라. 다음으로 RPC를 보라. rpc-whitelist를 쓰고 있다면 승인된 관리망은 계약의 일부이고, 넓은 RFC1918 범위는 그렇지 않다.
ss -tunp | grep -i transmission
인터페이스 카운터는 관찰을 뒷받침할 수 있지만, 어느 프로세스가 바이트를 만들었는지는 증명하지 못한다. 버려도 되는 전송을 하라, 먼저 동작하는 경로에서, 다음으로 시작 시 터널 없이, 그다음 중단과 재연결, 새로 만든 인터페이스를 거쳐서. 새 시도뿐 아니라 이미 열려 있던 연결도 시험하라. 규칙이 오래된 소켓에 적용되지 않았을 수 있으니, 날짜와 계정, 결과를 시험과 함께 기록하라.
체인 전체를 비우는 예제를 붙여 넣는 것은 구멍 하나를 여러 개와 맞바꾸는 일이므로, 규칙을 지우지 말고 더하라. 다섯 점검이 모두 통과하면 보장은 분명한데, 클라이언트 트래픽은 터널로 나가거나 아예 나가지 않으며, 그것을 강제하는 규칙은 터널 자체의 고장도 견딘다.