로그인은 되고 PWD도 되지만, 그다음 LIST는 클라이언트가 포기하거나 다른 데이터 모드로 넘어갈 때까지 멈춰 있습니다. 이 분리가 바로 특징인데, 포트 21로 가는 제어 연결은 건강한 반면 데이터 연결은 상대편이 도달할 수 없는 주소나 포트로 만들어지고 있습니다. NAT도 수행하는 VPN 게이트웨이 뒤에서 흔한 원인은 페이로드에 10.8.0.6 같은 터널 주소를 적는 FTP 명령입니다. 헤더 변환은 그 값에 절대 손대지 않습니다.

다음은 그 값이 어디서 오는지, 그리고 어느 상자가 그것을 바꿀 수 있는지입니다.

깨지는 것은 터널이 아니라 페이로드입니다

FTP는 데이터 종단점을 제어 스트림 안에 넣습니다. 능동 모드에서는 클라이언트가 자기 주소와 포트로 PORT를 보내고, 서버가 그 쌍으로 다시 접속합니다. 수동 모드에서는 서버가 쌍과 함께 227로 응답하고, 클라이언트가 그 대신 그 쌍으로 접속합니다.

두 형태 모두 이 주소의 이 포트로 접속하라는 같은 종류의 선언을 담습니다. IP와 TCP 헤더만 다시 쓰는 장비는 그 선언을 그대로 두므로, 한쪽 끝은 터널 건너편에만 존재하는 주소에 계속 도달하려 합니다. 제어 연결이 이미 건강하다고 선언된 뒤에 데이터 연결이 멈춥니다.

세 가지 모드, 세 가지 페이로드

아래 표는 어느 쪽에 접속하라고 지시하는지, 그리고 헤더만 다시 쓰는 NAT가 그 일에 무엇을 할 수 있는지를 보여 줍니다.

마지막 열은 가장 먼저 실패하는 것으로 읽으세요. 능동 모드에서는 서버가 사설 주소로 접속하고, 수동 모드에서는 클라이언트가 접속하며, FTPS에서는 페이로드가 암호문이라 중간 상자가 다룰 재료가 더 적습니다.

ModeValue in the control streamWho dials whomHeader-only NAT leaves
Active (PORT)client address and portserver dials the clienta server dialing an unreachable tunnel address
Passive (227)server address and portclient dials the servera client dialing an address it cannot route to
FTPSthe same values, inside TLSas aboveciphertext, so no rewrite happens at all

도우미를 변환이 일어나는 곳에 두세요

리눅스에서는 페이로드 재작성을 nf_conntrack_ftp 도우미가 합니다. 제어 연결을 지켜보고, 협상된 포트를 익히고, 데이터 흐름에 대한 기대를 만들며, NAT 상자에서는 페이로드 안의 주소와 포트를 다시 씁니다. 그것은 클라이언트 주소를 변환하는 장비에서만 도움이 됩니다. 클라이언트에, 또는 흐름을 전달만 하는 라우터에 올려도 세션에는 아무 변화가 없습니다.

이 세 명령은 모듈이 있는지, 연결되어 있는지, 세션이 열려 있는 동안 기대가 존재하는지를 보여 줍니다:

modprobe nf_conntrack_ftp
lsmod | grep nf_conntrack_ftp
conntrack -L expect | grep ftp

모듈을 올리는 것과 그것을 연결하는 것은 다릅니다. 4.7 이후 커널은 net.netfilter.nf_conntrack_helper=0과 함께 제공되므로, 도우미는 예를 들어 iptables -t raw -A PREROUTING -p tcp --dport 21 -j CT --helper ftp 같은 명시적 규칙을 기다립니다. 전송을 시도하는 동안 기대 목록이 비어 있다면 확인할 것은 모듈이 아니라 연결입니다.

수동 모드: 서버가 무엇을 알릴지 정하세요

수동 모드는 227 응답에 무엇을 넣을지 서버에 알려 줄 수 있어 결정적으로 만들기 쉽습니다. vsftpd에서는 pasv_address이며 pasv_min_port, pasv_max_port와 함께 쓰고, ProFTPD는 MasqueradeAddress와 PassivePorts를 사용합니다. 올바르게 알린 주소가 있으면 그쪽에서 무엇이든 다시 쓸 필요가 없어지므로 이것을 먼저 설정하세요.

그다음 정확히 그 포트 범위를 게이트웨이로 통과시켜, 예를 들어 -A FORWARD -i tun0 -p tcp --dport 30000:30100 -j ACCEPT로 규칙이 서버가 알리는 것과 맞게 하세요.

두 설정은 서로 맞아야 합니다. 30000-30100을 알리라고 지시된 서버를 두고 게이트웨이가 40000-40100을 허용하면 제어 대화는 건강해 보이는데 모든 데이터 연결이 죽는, 가장 도움이 안 되는 방식으로 실패합니다. 다른 무엇을 디버그하기 전에 숫자를 비교하세요.

두 가지 실패 특징, 그리고 FTPS가 없애는 것

LIST에서 멈추는 것은 세션의 첫 데이터 연결을 가리키며, 거기서는 주소 재작성과 기대가 모두 동작해야 합니다. LIST가 된 뒤 RETR에서 멈추는 것은 전송 자체, 즉 수동 범위나 터널 MTU를 가리킵니다. 그 두 번째 특징은 페이로드 문제가 아니며 도우미 설정으로 고쳐지지 않습니다.

TLS 위의 FTP는 도우미가 읽는 페이로드를 없앱니다. 중간 상자는 복호화할 수 없는 PORT나 PASV 값을 다시 쓸 수 없으므로, 남는 선택은 TLS를 끝내는 프록시, 제한된 범위에서 도달 가능한 주소를 알리는 서버, 또는 다른 전송 프로토콜입니다.

짧은 점검 순서

증상에서 바깥으로 나아가세요. PWD가 성공할 때 LIST가 실패하는지 확인하고, PORT나 227 페이로드 안의 주소를 잡고, 어느 장비가 그 주소를 변환하는지 물으세요. 거기에 도우미를 연결하고, 한 번의 전송 동안 기대 목록을 관찰한 뒤, 서버에서 수동 모드를 고치고 게이트웨이 규칙에 범위를 반영하세요.

데이터 경로의 실패와 대량 전송의 실패는 서로 다른 설정으로 이끄므로 분리해 두세요.

관련 글