SFTP 공유

This entry is part 34 of 48 in the series FreeNAS 서버 만들기

SMB 는 윈도우가 기본적으로 지원하는 파일 공유 프로토콜입니다. 하지만 외부에서는 접속하기가 쉽지 않다는 문제점이 있습니다.

그래서 이번에는 SFTP 프로토콜을 통해 파일 공유를 하는 방법에 대해 다뤄 보도록 하겠습니다.

SFTP는 SSH File Transfer Protocol 의 약자로서 SSH를 통한 파일 전송을 의미합니다. SSH를 통과하기 때문에 속도가 빠르고 보안이 높으며, FreeBSD 시스템에 기본적으로 설치되어 있기 때문에 구축이 간단하다는 장점이 있습니다.

FreeNAS 시스템에도 SSH 가 있으며, SFTP공유를 사용할 수는 있지만, FreeNAS 의 SSH를 인터넷에 노출시키는 것은 좋지 않은 생각입니다. 대신 SFTP 공유를 수행할 Jail 을 만들어서 SFTP 공유를 하도록 하겠습니다.

Jail 에서도 독립된 SSH 를 실행할 수 있으니, SFTP 감옥에 공유하고자 하는 리소스만 마운트하고, 권한을 제한한 다음, SFTP 만 실행할 수 있도록 제한하면 SFTP 를 안전하게 운용할 수 있을 것입니다. 거기다 Fail2Ban 까지 설치해 주면 무작위 대입 시도를 차단할 수 있겠죠.

그럼 만들어보겠습니다.

Jail 만들기

jail 의 이름은 SFTP

자동 시작 설정 해 주세요.

필요한 파일 마운트

SFTP 감옥의 /mnt/chroot 디렉토리 아래에 공유하고자 하는 디렉토리를 마운트 할 것입니다.

iocage exec SFTP mkdir -p /mnt/chroot/Media/Movie /mnt/chroot/Media/Drama /mnt/chroot/persnal/admion

미디어가 마운트 될 디렉토리와 개인 파일이 마운트 될 디렉토리를 만들어주었습니다.

iocage exec SFTP chown -R root:wheel /mnt/chroot

/mnt/chroot 는 chroot 시킬 디렉토리입니다. chroot 설정될 디렉토리의 소유자는 root 이고 그룹은 wheel 이여야 합니다.

iocage stop SFTP

감옥을 정지시켜 주고

  • /mnt/Data/Media/Movie/mnt/chroot/Media/Movie
  • /mnt/Data/Media/Drama/mnt/chroot/Media/Drama
  • /mnt/Data/persnal/admion/mnt/chroot/persnal/admion

마운트 해 줍니다.

계정 만들기

iocage console SFTP

감옥 안으로 로그인 해 주세요.

감옥 내부에 유저와 그룹을 만들어야 합니다. 먼저 media 그룹부터 만들겠습니다.

pw group add -n media -g 8675309

그룹의 이름은 달라도 되지만, GID 는 호스트와 동일해야 합니다.

그 후 admion 계정을 만들겠습니다.

pw user add admion -d /nonexistent -s /usr/sbin/nologin -u 1000 -g media -c "admion sftp only user"

admion 계정은 쉘을 사용할 수 없도록 nologin으로 설정하였고, UID 는 호스트와 동일하게 1000, 주 그룹은 media 로 설정하였습니다.

media 그룹과 admion 계정을 만들어주었습니다.

SSH 설정

vi /etc/ssh/sshd_config

sshd 설정 파일을 수정해줍니다. 수정해 주어야 할 부분은 아래와 같습니다.

Port 22

무슨 포트를 들을 것인지를 설정합니다. 여러 개의 포트를 들을 수도 있습니다.

LoginGraceTime 2m

몇 분 동안 로그인을 받을 지 설정합니다. 이 경우, 2분안에 로그인 하지 않으면 접속이 끊어집니다.

PermitRootLogin no

Root 로그인을 허용할지 설정합니다. 허용하지 않는 것이 좋습니다. no.

MaxAuthTries 6

몇 번의 로그인 시도를 허용할지 설정합니다. 이 경우 6번의 로그인을 허용하고, 암호가 6번 틀리면 접속이 끊어집니다.

PubkeyAuthentication no

공개 키 인증을 사용할지 설정합니다. 비밀번호를 이용할 것이므로 no.

PasswordAuthentication yes

암호 기반 인증를 사용할지 설정합니다. 비밀번호를 이용할 것이므로 yes

PermitEmptyPasswords no

빈 암호를 허용할지 설정합니다. no.

DisableForwarding yes

x11 포워딩, tcp 포워딩 등의 포워딩을 전부 금지합니다. sftp 전용으로 사용할 것이므로 포워딩이 필요하지 않습니다. yes.

GatewayPorts no

TCP 포워딩에 관련된 설정입니다. no.

TCPKeepAlive yes

연결이 끊어지지 않도록 KeepAlive 메세지를 보냅니다. yes.

Compression No

압축을 할지 설정합니다. 압축을 원한다면 Gzip-9 과 같은 식으로 압축 프로토콜의 이름을 입력하거나 yes 를 입력합니다.

Subsystem sftp internal-sftp

sftp 를 어덯게 동작시킬지 설정합니다. internal-sftp 으로 설정하면 openssh 자체적으로 sftp 를 수행함으로, chroot 설정을 하였을 때 추가적인 설정 없이 sftp 를 사용할 수 있습니다.

Match LocalPort 22
        AllowUsers admion
        ChrootDirectory /mnt/chroot
        ForceCommand internal-sftp

Match 설정은 아주 유용하고 편리한 설정입니다. Match 뒤에 붙은 조건에 부합하는 경우, 해당하는 유저에게 아래 설정들이 적용됩니다.

예를 들어, Match Address 192.30.1.3 이라는 설정이 있다면, 192.30.1.3 으로 접근한 유저에게 Match 아래의 설정이 적용됩니다.

AllowUsers 는 허용하는 유저를 의미합니다. AloowUsers admion asdf 라는 설정이 있다면, admionasdf 유저만 허용됩니다.

ChrootDirectory 는 루트 디렉토리를 변경하는 것입니다. chroot/mnt/chroot 라면 접속한 유저는 /mnt/chroot 보다 상위의 디렉토리에 접근할 수 없습니다.

ForceCommand 는 말 그대로 강제 명령입니다. 강제로 이후에 서술된 명령을 실행시키는데, internal-sftp 의 경우는 sftp를 실행시킵니다. 만약, ForceCommand exit 라는 설정을 입력했다면 로그인 하자 마자 로그아웃합니다. 어디에 쓰냐구요? 음… 그냥 그렇다구요.

Match 구문의 몇가지 예제를 살펴 보도록 하겠습니다.

Match Users admion
        PermitTTY no
        ChrootDirectory /mnt/chroot
        ForceCommand internal-sftp

위 설정을 사용할 경우, admion 유저가 접속할 경우, PTY를 금지하고, /mnt/chroot 를 chroot로 설정하며, internal-sftp 를 강제로 실행시킵니다.

Match Address 123.45.67.89
        AllowUsers asdf
        ForceCommand date '+%F  %r'

123.45.67.89 의 주소에서 로그인 할 경우 asdf 유저만 로그인을 허용하고, date ‘+%F %r’ 명령을 실행하고 연결을 끊습니다.

Match 키워드와 Allow, Deny 등의 제한을 잘 활용하면 다양한 설정이 가능합니다.

Match Address 192.168.1.123
        AllowUsers asdf root
        PermitRootLogin

192.168.1.123 으로 접속하였을 때, asdf 와 root 유저만 로그인 가능하며, root 로그인을 허용합니다.

(...)
Port 22
(...)
LoginGraceTime 1m
PermitRootLogin no
StrictModes yes
MaxAuthTries 3
(...)
PubkeyAuthentication no
(...)
PasswordAuthentication yes
PermitEmptyPasswords no
(...)
DisableForwarding yes
GatewayPorts no
TCPKeepAlive yes
Compression No
(...)
Subsystem sftp internal-sftp
(...)
#SFTP
Match LocalPort 22
        AllowUsers admion
        ChrootDirectory /mnt/chroot
        ForceCommand internal-sftp

위는 설정 예시입니다.

Fail2Ban

fail2ban 을 설치하여 SSH 에 무차별 대입 공격을 하는 것을 막을 것입니다.

fail2ban을 ssh 에 적용하는 것도 nginx fail2ban 과 거의 동일하게 진행됩니다. 참고하시면 좋습니다.

레포 바꾸기

pkg 와 port – 레포 바꾸기‘ 를 참고하여 레포를 최신으로 바꿔 주세요.

fail2ban 설치

pkg install py36-fail2ban

fail2ban 만 설치하면 됩니다.

IPFW 구성

vi /etc/rc.conf

firewall_enable="YES"
firewall_type="workstation"
firewall_logging="YES"
firewall_myservices="22/tcp"
firewall_allowservices="any"
firewall_logdeny="YES"

위 설정을 추가합니다. 22/tcp 포트를 연 것이 보일 것입니다. 설정하였다면 ipfw 를 시작해 줍니다.

service ipfw start

Jail.d 설정 만들기

vi /usr/local/etc/fail2ban/jail.d/ssh-ipfw.local

[ssh-ipfw]

enabled = true
filter = sshd
action = ipfw[name=SSH, port=22 protocol=tcp]
logpath = /var/log/auth.log
findtime = 600
maxretry = 3
bantime = 3600
ignoreip = 192.168.1.0/24

ssh 인증을 3번 이상 틀리면 1시간동안 차단하는 룰을 사용하였습니다.

ignoreip 는 차단하지 않는 IP 또는 대역입니다. 192.168.1.0/24 대역은 차단하지 않습니다.

IPFW action 수정

vi /usr/local/etc/fail2ban/action.d/ipfw.conf

actionstart = ipfw add 2410 <blocktype> tcp from "table(100)" to <localhost> 22
actionban = ipfw table 100 add <ip>
actionunban = ipfw table 100 delete <ip>
localhost = me

위와 같이 해당되는 설정을 찾아 수정해 주세요.

Fail2Ban 서비스 등록

sysrc fail2ban_enable="YES"

Jail 시작시 자동으로 시작되도록 하고

service fail2ban start

Fail2Ban 을 시작해 줍니다.

SSH 시작

sysrc sshd_enable="YES"

Jail 시작시 자동으로 시작되도록 하고

service sshd start

sshd 를 시작해 줍니다.

포트포워딩

22 포트를 그대로 사용하는 것은 좋은 생각이 아닙니다. 공격이 너무 많이 들어오기 때문입니다. 외부 포트를 22가 아닌 다른 포트로 바꾸어 주는 것이 좋습니다. 잘 알려진 포트등록된 포트 를 피해서 (예를 들어 1234) 등록해주는 것이 좋습니다.

SFTP Jail 22외부 1234 TCP 포트

접속

윈도우의 경우는 RaidriveFileZila 와 같은 프로그램을 이용해 사용할 수 있습니다.

안드로이드의 경우는 SFTP 공유를 지원하는 파일 탐색기를 사용하면 됩니다. 많은 수의 파일 탐색기 어플에서 SFTP 공유를 지원합니다.

마치면서

이로서 SFTP 공유를 설정하고 Fail2Ban으로 무차별 대입 공격을 막는 방법을 알아 보았습니다.

다음 포스팅은 FEMP 를 구축하는 것에 대해 다룰 것입니다.

시리즈 네비게이션<< SoftEther VPN웹 서버 – FEMP >>

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다