RHEL 8 이상 tcp_wrapper를 이용한 SSH ACL 설정 (hosts.allow / hosts.deny)
Table of Contents
- 01. RHEL 8에서 SSH 접근 제어 방법 변경에 대한 이야기
- 02. TCP Wrapper란 무엇인가 ?
- 03. RHEL 8에서의 tcp_wrapper 설치 및 바인딩 설정
- 04. sshd.service와 sshd.socket 차이
- 05. Reference Document
01. RHEL 8에서 SSH 접근 제어 방법 변경에 대한 이야기
먼저 이 글의 핵심부터 이야기하자면, RHEL 8 버전부터 SSH 데몬에서 libwrap을 지원하지 않기 때문에 접근 제어를 systemd에서 소켓 바인딩 방식을 통해 설정해야 한다. 왜냐하면 RHEL 8 이상부터는 SSH 접근 제어(ACL)를 설정할 때 TCP Wrapper를 없애버리고 firewalld를 이용하는 것이 권장되기 때문이다.
그럼 이 글에서 더 다양하게 설정 가능하고 유연성이 좋은 firewalld 방식이 아닌 TCP Wrapper를 이용한 방식을 언급하는 이유를 설명하겠다.
이유는 간단하다. firewalld를 사용하지 못하는 서비스 환경이 존재하기 때문이다. 예를 들어, 쿠버네티스 및 컨테이너 환경이나 특정 네트워크 설정을 가진 복잡한 시스템에서는 firewalld를 이용하여 모든 정책을 관리하고 분석하는 것이 매우 힘들 수 있다. 이런 경우, firewalld를 중지하고 개별적으로 보안 설정을 하는 것이 더 나을 수 있다.
또한, 특정 보안 요구 사항이나 규제 준수를 위해 TCP Wrapper를 사용해야 하는 경우도 있을 수 있다. 그리고 레거시 시스템과의 통합이 필요한 상황에서도 TCP Wrapper가 유용할 수 있다.
따라서, 다양한 환경과 요구에 맞춰 적절한 접근 제어 방식을 선택하는 것이 중요하다.
02. TCP Wrapper란 무엇인가 ?
TCP Wrapper는 libwrap 라이브러리를 사용하여 특정 클라이언트의 접근을 허용하거나 차단하는 기능을 제공한다.
서비스에 대한 연결 시도가 있을 때, TCP Wrapper는 /etc/hosts.allow와 /etc/hosts.deny 파일을 확인하여 접근을 허용할지 결정하는데, 만약 접근이 허용되면, 이후의 통신에는 간섭하지 않는다. 접속 기록은 syslog를 통해 /var/log/secure 또는 /var/log/messages에 저장된다.
허용 및 차단 순서
- /etc/hosts.allow 파일을 먼저 읽어 허용 규칙을 확인한다. 일치하는 규칙을 찾으면 연결을 허용한다.
- /etc/hosts.allow에서 해당 규칙을 찾지 못하면, /etc/hosts.deny 파일을 읽어 차단 규칙을 확인한다.
- 참조 문서 : 2.6.2. TCP 래퍼 구성 파일
03. RHEL 8에서의 tcp_wrapper 설치 및 바인딩 설정
Step 01. tcp_wrappers 패키지 설치
$ sudo dnf install tcp_wrappers
Step 02. systemd를 이용한 ssh 연결을 위한 설정파일 복사 및 설정
sshd@.service 파일을 /etc/systemd/system으로 복사한다.
$ cp /usr/lib/systemd/system/sshd@.service /etc/systemd/system/
복사한 파일에서 /usr/sbin/tcpd를 사용할 수 있게 수정한다.
$ vi /etc/systemd/system/sshd@.service
- ExecStart=-/usr/sbin/sshd -i $OPTIONS $CRYPTO_POLICY
+ ExecStart=@-/usr/sbin/tcpd /usr/sbin/sshd -i $OPTIONS $CRYPTO_POLICY
Step 03. sshd.socket 으로 SSH 시작
sshd.service를 중지하고 sshd.socket을 시작한다.
$ systemctl stop sshd; systemctl start sshd.socket
Step 04. ACL 설정
원하는대로 ACL을 설정한다.
# /etc/hosts.allow
sshd: 1.2.3.4/32, 10.0.0.0/8, 192.168.122.0/2
# /etc/hosts.deny
sshd: ALL
Step 05. sshd.socket을 영구적으로 설정
$ systemctl disable sshd; systemctl enable sshd.socket
04. sshd.service와 sshd.socket 차이
sshd.socket은 systemd socket 기능을 이용하는 것이다.
sshd.service는 sshd 데몬이 계속 실행되고 있다가 새로운 연결을 sshd 데몬이 관리한다.
반면 sshd.socket은 systemd에서 관리되어 sshd가 계속실행되는 것이 아니라 하나의 클라이언트에 하나를 처리하는 방식으로 연결된다.
따라서 LISTEN 상태의 22 포트를 확인하게 되면 sshd.service는 sshd 데몬이 수신 대기상태로 있다가 클라이언트가 연결되면 sshd에서 fork 방식으로 ssh 연결이 성립된다.
sshd.socket의 LISTEN 상태 22 포트를 보면 systemd가 22번 포트를 수신 대기상태로 있다가 클라이언트가 연결되었을 때 systemd에서 관리되는 ssh 연결이 성립된다.
[참고] SSH 포트 확인 시 tcp6(:::6)로만 표시되는 의미
포트 확인 시 tcp6만 :::22로 LISTEN 되어 있어도 일반적으로 IPv4, IPv6 모두 지원한다는 의미이다. 이는 시스템이 IPv6 소켓을 사용하여 포트를 열 때 기본적으로 dual-stack 모드로 동작하기 때문이다.
해당 기능은 ‘/etc/ssh/sshd_config’ 설정 파일에서 아래 옵션에 의한 결정된다.
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::
- ListenAddress 은 sshd가 사용할 IPv4나 IPv6와 같은 IP 주소 유형 선택
- 0.0.0.0 및 :: 은 sshd에서 IPv4 또는 IPv6 주소가 아닌, 모든 인터페이스를 사용하는지 확인
위 설정이 주석처리 되어 있다면, Default 설정을 따른다. 이는 man sshd_config에서 확인 가능하다.
기본값은 AddressFamily는 any이며, ListenAddress 현재 기본 라우팅 도메인의 모든 로컬 주소에서 Listen 한다.