FTP를 설치하려고 한 이유

한 서버에 세들어 사는 다른 사이트가 있는데, 이 사이트를 관리하는 사람은 다른 사람이다. 이 사람이 셋방(사이트)을 관리하려면 어떻게 해야 할까?

관리자인 내가 관리하듯이 셸 로그인 정보를 공유하면 방법은 간단하겠지만, 이건 동거인에게 내 캐비닛 서랍까지 열 수 있는 마스터키를 주는 거나 다름이 없다. 그리고 무엇보다 그러한 열쇠꾸러미는 너무 권한이 많고 복잡하다. 필요한 건 오직 파일 업로드 및 관리 뿐. 그렇다면 탐색기처럼 단순하게 관리할 수 있는 방법이 좋겠다.

File Transfer Protocol은 이 풀네임 자체가 기능을 설명한다. 파일을 전송하는 규약이다. 성능면에서 아쉬운 부분도 있지만, 클라이언트 선택지가 다양하니 추천하기에 딱이다. 일반적인 인식으로 보안이 취약하다는 단점도 있지만, TLS 인증을 넣어준다면 암호화도 된다. 간편하게 도입하기엔 PureFTPd가 가장 좋아보였다.

설치 과정

apt-get으로 설치하기

Ubuntu 서버를 운영하고 있으니 모두 Ubuntu 기준이다. 별도의 저장소 등록 없이 간편하게 설치된다. 사용자 계정 등 데이터 저장 방식에 따라 MySQL 등 다른 바리에이션이 있지만, 그쪽은 DB 관리툴도 필요하기 때문에 간편하게 느껴지지 않으니까 기본적인 방식으로 진행하려고 한다.

$ sudo apt-get install pure-ftpd

config

$ sudo su

$ cd /etc/pure-ftpd/

$ ls conf

이곳에 들어가면 아래 설정 중 일부만 채워져 있을 것이다.

  • AltLog: 로그를 저장할 경로. 기본값으로 지정되어 있다.
  • Bind: FTP 접속을 수신할 메인 포트 (ex: ,9999)
  • FSCharset: 파일 시스템 문자셋 (보통 UTF-8)
  • ForcePassiveIP: 패시브 연결시 서버 자기 자신의 IP 설정. 대체로 VPS, 개인서버를 쓰더라도 PC의 IP는 내부 전용이라 외부에서 보이는 IP를 별도로 지정해야 한다. FileZila에서는 설정 없이도 연결이 되지만, 메시지가 뜨면서 IP 불일치를 무시할 것인지 계속 물어보므로 설정하는게 좋다.
    참고로 파일 전송시 클라이언트의 포트를 개방해야 하는 액티브 연결보다는 서버 포트로 대응하는 패시브 연결이 더 호환성에 유리하다.
  • MaxClientsNumber: 최대 접속 사용자수
  • MinUID: 신뢰할 유저 번호(UID)의 최저 번호. 일반 유저는 1000부터 시작하는 리눅스의 UID에 맞게 기본값이 설정되어 있어서 그보다 낮은 시스템 유저로 로그인을 막는 보안 장치다.
  • NoAnonymous: 익명 로그인 금지. (ex: yes)
  • PAMAuthentication: 인증 (ex: yes)
  • PassivePortRange: 패시브 연결시 파일 전송에 사용할 서버 포트 번호 범위. 위 Bind와 함께 운영체제 및 서비스의 포트 개방을 반드시 설정해줘야 한다. VPS 네트워크 설정도 꼭 확인하자.
  • PureDB: 데이터베이스가 저장된 pdb 파일 경로
  • TLS: TLS 연결 플래그
    • 0: (기본값) TLS 보안 연결을 사용하지 않음. 비밀번호 평문 전송이라 매우 위험한 형태
    • 1: TLS 연결도, 비보안 연결도 모두 허용.
    • 2: TLS 연결이 아니면 거부. 익명 로그인도 불가. (추천)
      이 설정 이후 인증서 설정을 하지 않으면 접속을 할 수 없다.
    • 3: TLS 연결만 허용. 평문 세션은 물론 평문 데이터 전송도 거부.
  • TLSCipherSuite: TLS 암호화에 쓰일 CipherSuite로, 암호화 방식이라 보면 된다. 기술의 발전으로 뚫려버린 과거의 암호화 방식을 쓰지 않도록 HIGH라는 기본값을 유지하길 추천한다.
  • UnixAuthentication: Unix 인증 로그인 허용 여부. 기본값이 no다. 인증에 자체 DB를 쓰는 설정으로 진행한다는 가정이다.
  • VerboseLog: FTP 명령어로 받은 것을 일일히 로그에 기록해준다.

알아보았으니 대충 값을 채워보았다.

$ cd /etc/pure-ftpd/

$ echo (value) > (key)
KeyValue
Bind,8585
(21, 22 같은 알려진 포트는 피하자)
ForcePassiveIP(서버의 외부 IP)
AWS라면 StaticIP에 해당한다.
MaxClientsNumber50
PassivePortRange50000 51000
(다른 서비스와 겹치지 않게 주의한다)
TLS2
VerboseLogyes
새롭게 저장한 내용만…

사용자 계정 추가

pure-ftpd에 사용하기 위한 계정은 두 가지가 필요하다. 실제 시스템에 추가한 사용자, 그리고 인증에 쓰이는 가상의 사용자 모두 필요하다.

  • 리눅스 시스템 계정
    • FTP 계정끼리 공유하는 group (groupadd)
    • 그 그룹에 속하는 시스템 사용자 (useradd)
  • PureDB나 MySQL 같은 데이터베이스에 존재하는 계정
    • 만들 때 옵션으로 시스템 계정의 상기 계정을 연결하면서 비밀번호를 별도로 지정
  • username
-- run as su
# groupadd ftpusers

# useradd -g ftpusers -d /dev/null 시스템계정이름

# usermod --shell /usr/sbin/nologin 시스템계정이름

# pure-pw useradd 로그인아이디 -u 시스템계정이름 -d FTP홈디렉토리

# pure-pw mkdb

FTP 홈디렉토리는 FTP 클라이언트에서 ‘/’로 표시되는 최상위 루트가 된다. 루트로 표시하지 않게 하는 PureFTPd의 옵션도 있지만 그런 위험한 일은 굳이 할 필요가 없다.

TLS 인증서 인식 (Let’s encrypt)

Let’s encrypt 인증서를 이미 발급했다고 가정하고 진행해본다. 생성된 파일의 일부분을 합쳐서 인식시키고 서비스를 재시작하면 된다.

-- run as su
# cat /etc/letsencrypt/live/mydomain.com/fullchain.pem /etc/letsencrypt/live/mydomain.com/privkey.pem > /etc/ssl/private/pure-ftpd.pem

# sudo service pure-ftpd restart

Troubleshooting

PASS 명령어 이후 연결이 중단된다. 로그인이 안 된다.

pam_unix(pure-ftpd:auth): authentication failure; logname= uid=0 euid=0 tty=pure-ftpd ruser=사용자이름 rhost= user=사용자이름

system pure-ftpd status에 이러한 로그가 쌓여있고, FileZilla에서도 PASS 명령어 이후 심각한 오류 발생으로 연결이 중단되는 경우가 있다. 이는 PureDB를 인식하지 못하고 엉뚱한 방식으로 인증한 탓이다. (시스템 로그인)

$ ln -s /etc/pure-ftpd/conf/PureDB /etc/pure-ftpd/auth/PureDB

이 방식으로 auth 수단에 PureDB가 정상적으로 등록된다. 물론 pure-pw useradd -> pure-pw mkdb까지 잘 끝마쳤다는 가정이다.

MLSD 명령어 이후 FTP 클라이언트 반응 없음. 파일 목록 표시가 안 된다.

Passive 연결을 감지했지만, Passive에 필요한 포트가 닫혀 있다. PassivePortRange 범위의 모든 포트를 개방해야 한다.

  1. iptables 또는 ufws 방화벽의 설정 여부 및 화이트리스트 추가
  2. VPS 설정에서 포트 개방. TCP로 지정하여 열어준다.

파일을 읽을 수 있으나 쓸 수가 없다.

권한이 불일치한 경우인 듯 하다. chmod로 바꾸면 되겠지 싶지만, 당장 신규 파일이 pure-pw useradd에서 지정한 시스템 사용자 계정으로 만들어지기 때문에 모두 chown하여 소유자를 일치시키는게 가장 좋다.

$ sudo chown -hR FTP시스템계정:FTP시스템그룹 FTP홈디렉토리

다른 케이스가 있는지 추가로 알아볼 예정이다.

2년차 개발자 이진백입니다. 현재 일본에서 웹 프로그래머로 근무중입니다. 주로 Java, Vue (Nuxt), TypeScript 언어를 활용하고 있습니다. 취미로 C#과 Windows Universal Store App을 오래 만져왔고, 개인 서버 운영에도 관심이 많습니다. 최신 이슈를 알기 쉽게 전달해드리도록, 더욱 더 노력하겠습니다.