[RHEL8-9] TCP Wrapper 없이 방화벽(Firewall)과 SSH로 IP 및 포트 제한하기
리눅스 서버의 보안 취약점 조치 항목 중 하나는 '접속 IP 및 포트 제한'입니다. SSH, Telnet, FTP 같은 주요 서비스는 외부로 노출될 경우 시스템 정보가 탈취될 위험이 있기 때문에, 방화벽(Firewall)을 통해 허용된 IP만 접근하도록 제어하는 것이 필요합니다.
RHEL 7까지는 TCP Wrappers
기능을 통해 이런 접근 제어를 설정했습니다. 하지만 RHEL 8부터는 hosts.allow
및 hosts.deny
파일이 제거되면서, 이제는 방화벽을 통해 접근 제한을 구현해야 합니다.
TCP Wrappers 제거와 그 대안
sshd
접근을 제한할 수 있었습니다 <RHEL7 이하># cat /etc/hosts.deny sshd : 59.63.166.102 sshd : 141. sshd : 50.
이 설정은 지정된 IP 또는 IP 대역의 클라이언트만 SSH 접근을 차단하는 효과가 있었으며, 방화벽 설정과는 별개로 동작했습니다.
그러나 RHEL 8부터는 TCP Wrappers 기능이 더 이상 지원되지 않습니다. Fedora 프로젝트에서도 아래와 같은 이유로 해당 기능의 제거를 공식화했습니다.
TCP Wrappers는 20년 전에는 유용한 보안 도구였지만, 오늘날의 리눅스 환경에서는 iptables나 nftables 같은 네트워크 레벨 방화벽 도구가 더 효과적이며, TCP Wrappers는 유지 관리나 보안 대응 측면에서 더 이상 적절하지 않습니다.
TCP Wrappers 없이 SSH 접근 제한하기
TCP Wrappers가 사라진 이후, SSH 접근 제어는 주로 방화벽(firewalld
)을 통해 수행해야 합니다. 다만 방화벽을 사용하지 않거나 별도의 보안 정책이 필요한 경우, 다음과 같은 대안이 있습니다
- 서비스 자체의 접근 제한 기능 활성화
- 리눅스 방화벽 설정
- 외부 방화벽 설정
서비스가 자체적으로 제공하는 접근 제한 기능이 있다면 해당 기능을 우선적으로 활용하는 것이 좋습니다. 그렇지 않은 경우에는 시스템 수준에서 방화벽을 통해 IP 접근을 제어해야 합니다.
SSH 자체 접근 제한 기능 활성화
환경
Red Hat Enterpriese Linux 7
Red Hat Enterpriese Linux 8
Red Hat Enterpriese Linux 9
SSH 데몬(sshd
)은 AllowUsers
지시어를 통해 특정 사용자 또는 IP 대역에서만 접근을 허용하는 기능을 제공합니다. 아래는 해당 기능에 대한 man
페이지 설명입니다
# man sshd_config ... AllowUsers This keyword can be followed by a list of user name patterns, separated by spaces. If speci‐ fied, login is allowed only for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny directives are processed in the following order: DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups.
즉, USER@HOST
형식을 사용하면 IP 주소(CIDR 포함) 기준으로 SSH 접근을 제한할 수 있습니다.
/etc/ssh/sshd_config
파일에 AllowUsers
항목을 추가하면 특정 IP 또는 IP 대역에서만 SSH 접근을 허용할 수 있습니다. 기본적으로 해당 항목은 비어 있으므로 직접 추가해야 합니다.
# vim /etc/ssh/sshd_config ... AllowUsers *@192.168.180.* AllowUsers *@192.168.155.92 AllowUsers *@192.168.155.88 # systemctl reload sshd
sshd의 경우 reload를 제공합니다. reload는 restart와 다르게 프로세스 종료 없이 설정을 불러오기 때문에 PID가 변경되지 않습니다. 따라서 연결되어 있는 다른 서비스와의 관계를 유지하게 해주는 유용한 기능입니다.
AllowUsers를 사용하게 되면 이제 지정된 IP 이외의 다른 곳으로부터의 접속은 차단되게 됩니다. 만약 차단된 대역에서 접근하면 아래와 같이 Permission denied로 표시되게 됩니다.
# ssh 192.168.155.76 root@192.168.155.76's password: Permission denied, please try again.
Firewalld 를 이용한 SSH 접근 제한
firewalld
는 매우 유연한 방화벽 도구로, 사용자의 목적에 따라 다양한 IP 제한 정책을 설정할 수 있습니다. 이 절에서는 두 가지 대표적인 방식으로 접근 제한 방법을 설명합니다.
- 모든 서비스를 활성화하고 SSH만 IP를 제한하는 방법
- firewalld의 다른 서비스는 건드리지 않고 SSH만 제한하는 설정
[Firewall 방법-1] 모든 대역 허용하고 SSH만 제한하기
이 방법은 방화벽 사용을 원하지 않고 SSH만 접근 제어하고 싶은 경우에 사용할 수 있습니다. Firewalld를 안 쓰는 것이 아니라 Firewalld를 기동한 뒤에 모든 포트를 허용하는 방식입니다. 대부분의 기업들이 외부 방화벽을 사용 중이기 때문에 리눅스 방화벽은 꺼두는 그런 환경에서 유용합니다. 이렇게 리눅스에서 모든 포트를 오픈하면 외부 방화벽에 의해서만 제어가 가능합니다.
순서
- 방화벽 활성화
- SSH를 제외한 모든 포트 허용
- SSH 포트 IP 제한
설정을 시작하기 전에 방화벽을 잘못 건드리면 SSH 접속이 안될 수 있으므로 콘솔에서 작업을 권장 드립니다.
- 방화벽 시작: 가장 처음 방화벽 서비스를 기동합니다.
[root@rhel8 ~]# systemctl enable firewalld --now Created symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service → /usr/lib/systemd/system/firewalld.service. Created symlink /etc/systemd/system/multi-user.target.wants/firewalld.service → /usr/lib/systemd/system/firewalld.service.
- SSH 서비스 차단SSH의 경우 기본으로 활성화되어 있을 수 있는데, 22번 포트는 나중에 특정 IP 대역에서만 오픈할 예정이므로 미리 차단합니다.
[root@rhel8 ~]# firewall-cmd --remove-service=ssh --permanent success [root@rhel8 ~]# firewall-cmd --reload success [root@rhel8 ~]# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: enp1s0 sources: services: cockpit dhcpv6-client dns ports: protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
--list-all 명령을 이용해 현재 설정 내역을 확인해 보면 “ssh”가 사라진 걸 보실 수 있습니다. 이제 리눅스 방화벽에 의해 22번의 접근은 모두 차단됩니다.
- ssh를 제외한 모든 포트 오픈
[root@rhel8 ~]# firewall-cmd --permanent --add-port=1-21/tcp success [root@rhel8 ~]# firewall-cmd --permanent --add-port=1-21/udp success [root@rhel8 ~]# firewall-cmd --permanent --add-port=23-65535/tcp success [root@rhel8 ~]# firewall-cmd --permanent --add-port=23-65535/udp success [root@rhel8 ~]# firewall-cmd --reload success
[root@rhel8 ~]# firewall-cmd --permanent --add-port=1-21/tcp success [root@rhel8 ~]# firewall-cmd --permanent --add-port=1-21/udp success [root@rhel8 ~]# firewall-cmd --permanent --add-port=23-65535/tcp success [root@rhel8 ~]# firewall-cmd --permanent --add-port=23-65535/udp success [root@rhel8 ~]# firewall-cmd --reload success
--permanent 옵션을 추가하면 설정 파일에만 룰이 적용되므로, 현재 런타임 환경에 적용하려면 firewall-cmd --reload 명령을 사용해야 합니다.
이제 다시 조회해보면 22번 포트를 제외한 전체 포트가 오픈되어 있는 것을 확인할 수 있습니다.
[root@rhel8 ~]# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: enp1s0 sources: services: cockpit dhcpv6-client dns ports: 1-21/tcp 1-21/udp 23-65535/tcp 23-65535/udp protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
- 특정 대역만 ssh허용 <rich Rule>firewalld는 리치 규칙(Rich Rule)을 이용해 기본 firewalld 구문으로 할 수 없는 유연한 사용자 지정 방화벽 규칙을 작성할 수 있습니다.
[root@rhel8 ~]# firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.168.155.0/24 service name=ssh accept' --permanent success [root@rhel8 ~]# firewall-cmd --reload success
위 명령은 192.168.155.0/24 대역에서 접근하는 IP만 허용하는 리치 규칙을 설정하는 예제입니다.
<리치규칙 사용 방법>
- -add-rich-rule='<RULE>': 지정된 영역 또는 기본 영역에 <RULE>을 추가합니다.
- -remove-rich-rule='<RULE>': 지정된 영역 또는 기본 영역에서 <RULE>을 제거합니다.
리치 규칙 제거는 아래와 같이 생성 명령어에서 add를 remove로 변경하면 됩니다.
# firewall-cmd --remove-rich-rule='rule family=ipv4 source address=192.168.155.0/24 service name=ssh accept' --permanent
적용된 방화벽 규칙을 조회하면 맨 아래에 리치 규칙이 정상적으로 설정된 것을 확인할 수 있습니다. 이제 이 서버의 SSH는 192.168.155.0/24 소스를 가진 서버에서만 가능합니다.
[root@rhel8 ~]# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: enp1s0 sources: services: cockpit dhcpv6-client dns ftp ports: 1-21/tcp 1-21/udp 23-65535/tcp 23-65535/udp protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" source address="192.168.155.0/24" service name="ssh" accept
[Firewall 방법-2] 기존 방화벽 설정 유지, SSH만 별도 제한
이미 firewalld
가 활성화되어 있고 다른 서비스도 방화벽을 통해 제어 중이라면, 기존 설정을 유지하면서 SSH에 대해서만 접근 제어를 추가하는 방식이 적절합니다. 이때도 Rich Rule을 사용하여 IP별 접근을 지정할 수 있습니다.
순서:
- firewalld에서 SSH 포트 제거
- 리치 규칙을 이용해 SSH 포트에 접속할 IP 추가
- 기존 SSH 포트 제거
[root@rhel8 ~]# firewall-cmd --remove-service=ssh --permanent success [root@rhel8 ~]# firewall-cmd --reload success
- rich Rule 추가리치 규칙은 원하는 만큼 계속 추가할 수 있습니다. 접근 가능한 IP 대역은 물론 특정 IP를 지정해서도 추가할 수 있습니다.
[root@rhel8 ~]# firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.168.155.92 service name=ssh accept' --permanent success [root@rhel8 ~]# firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.168.155.76 service name=ssh accept' --permanent success [root@rhel8 ~]# firewall-cmd --reload success
아래는 두 개의 리치 규칙이 설정된 모습입니다.
[root@rhel8 ~]# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: enp1s0 sources: services: cockpit dhcpv6-client dns ftp ports: 1-21/tcp 1-21/udp 23-65535/tcp 23-65535/udp protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" source address="192.168.155.76" service name="ssh" accept rule family="ipv4" source address="192.168.155.92" service name="ssh" accept
방화벽에서 접근이 거부되는 경우 아래와 같은 오류가 발생합니다.
[root@rhel82 ~]# ssh 192.168.155.88 ssh: connect to host 192.168.155.88 port 22: No route to host
마치며
TCP wrappers 기능은 이제 firewalld로 대체되었지만, 대부분의 리눅스 시스템에서 firewalld를 사용하지 않아 보안 취약점 조치 시 처리 방안에 대한 고민이 생기기 마련입니다. sshd는 자체적으로 접속 제한 기능을 제공하지만, vsftpd와 같이 그런 기능이 없는 경우 리눅스 firewalld로 진행하거나 예외 처리를 고려해야 합니다. 다행히 많은 사람들이 사용하는 sshd는 IP 제한 기능을 제공하고 있습니다.
참고
https://fedoraproject.org/wiki/Changes/Deprecate_TCP_wrappers [fedora TCP Wrappers]
댓글
댓글 쓰기