Red Hat Certified System Administrator (RHCSA) #12 firewalld와 SSH 키 인증

11 분 소요

#11 사용자/그룹에서 UID,GID와 sudo, ACL, 비밀번호 정책으로 사용자 보안을 잡았다면, 이번에는 시스템 바깥에서 들어오는 접근을 통제하는 두 축을 다룹니다. 하나는 firewalld로 어떤 포트와 서비스를 열지 결정하는 것이고, 다른 하나는 SSH 키 인증으로 비밀번호 없이 안전하게 원격 접속하는 것입니다.

두 주제 모두 RHCSA 단골입니다. firewalld는 “이 서비스(또는 포트)를 영구히 허용하라"는 형태로 거의 매번 출제되고, SSH 키 인증은 “이 사용자가 키로 로그인할 수 있게 설정하라"는 작업으로 나옵니다. 그리고 두 작업 모두 영구 적용을 빠뜨리면 0점입니다. firewalld는 --permanent를, SSH는 권한과 sshd 재시작을 놓치는 순간 채점 스크립트가 실패합니다. 그래서 이번 글은 명령 하나하나를 영구 적용 관점에서 정리하겠습니다.

firewalld란 무엇인가 #

RHEL의 기본 방화벽은 firewalld입니다. 내부적으로는 nftables(예전에는 iptables)를 다루지만, 우리는 firewall-cmd라는 명령으로 추상화된 규칙을 다룹니다. firewalld의 가장 큰 특징은 zone(영역) 이라는 개념입니다.

zone은 “이 네트워크 트래픽을 얼마나 신뢰하는가"에 따라 묶어 둔 규칙 집합입니다. 같은 80번 포트라도 신뢰하는 내부망에서 들어오면 허용하고, 신뢰하지 않는 외부에서 들어오면 막을 수 있습니다. 자주 쓰는 zone은 다음과 같습니다.

zone성격
public기본 zone. 신뢰하지 않는 공개망. 명시적으로 연 것만 허용
trusted모든 트래픽 허용. 완전히 신뢰하는 망
drop들어오는 모든 패킷을 응답 없이 폐기
block들어오는 연결을 거부(reject)하되 응답은 보냄
internal / dmz / work용도별 사전 정의 zone

RHCSA에서는 대부분 기본 zone인 public에 규칙을 추가합니다. 다만 “특정 출발지 주소는 다른 zone으로 처리하라” 같은 source 기반 문제가 나올 수 있으므로 zone 개념 자체를 알아 두어야 합니다.

firewalld 상태 확인 #

작업 전에 firewalld가 동작 중인지, 그리고 어떤 zone이 활성인지 먼저 확인하겠습니다.

# firewalld 서비스 상태 확인
systemctl status firewalld

# 활성화되어 있지 않다면 시작하고 부팅 시 자동 시작 등록
systemctl enable --now firewalld

# 현재 활성 zone과 그 zone에 묶인 인터페이스 확인
firewall-cmd --get-active-zones

# 기본 zone 확인
firewall-cmd --get-default-zone

--get-active-zones는 실제로 트래픽이 흐르는 zone과 거기에 묶인 인터페이스를 보여 줍니다. 예를 들어 다음처럼 출력됩니다.

public
  interfaces: ens160

이 출력은 ens160 인터페이스로 들어오는 트래픽이 public zone 규칙을 따른다는 뜻입니다. 따라서 별도 지정이 없으면 public에 규칙을 넣으면 됩니다.

firewall-cmd로 서비스,포트 열기 #

firewalld에서 무언가를 허용하는 방법은 크게 두 가지입니다. 서비스 이름으로 열기포트 번호로 열기입니다.

서비스로 열기 #

firewalld는 잘 알려진 서비스의 포트를 이름으로 묶어 둔 정의를 가지고 있습니다. http는 80, https는 443, ssh는 22처럼 이름만 지정하면 해당 포트가 열립니다. 사용 가능한 서비스 목록은 다음으로 봅니다.

# firewalld가 아는 서비스 이름 목록
firewall-cmd --get-services

서비스를 추가하는 명령은 다음과 같습니다.

# public zone에 http 서비스 허용 (현재 세션에만 적용. 재부팅하면 사라짐)
firewall-cmd --add-service=http

이 명령은 지금 당장은 동작하지만, 재부팅하면 사라집니다. 영구 적용은 잠시 뒤에 따로 다루겠습니다.

포트로 열기 #

표준 서비스가 아닌 임의의 포트를 열려면 포트와 프로토콜을 직접 지정합니다.

# 8080/tcp 포트 허용 (현재 세션에만 적용)
firewall-cmd --add-port=8080/tcp

# 범위로 지정도 가능 (5900〜5910/tcp)
firewall-cmd --add-port=5900-5910/tcp

--add-port는 항상 포트/프로토콜 형식입니다. 프로토콜(tcp 또는 udp)을 빠뜨리면 명령이 실패하므로 주의하겠습니다.

–permanent와 –reload: 영구 적용의 핵심 #

여기가 RHCSA에서 가장 많이 점수를 잃는 지점입니다. firewalld의 규칙에는 두 개의 분리된 설정 집합이 있습니다.

  • runtime(현재 적용): 지금 메모리에 올라가 동작 중인 규칙. 재부팅하면 사라집니다.
  • permanent(영구 설정): 디스크에 저장되어 재부팅 후에도 유지되는 규칙. 다만 저장한다고 바로 적용되지는 않습니다.

--permanent 없이 --add-service=http만 하면 지금은 열리지만 재부팅 후 닫힙니다. 반대로 --permanent만 붙이면 디스크에는 저장되지만 지금 당장은 적용되지 않습니다. 그래서 둘 다 만족시키는 표준 패턴은 다음 두 단계입니다.

# 1) 영구 설정에 규칙을 저장
firewall-cmd --permanent --add-service=http

# 2) 영구 설정을 runtime으로 다시 읽어 들여 지금도 적용
firewall-cmd --reload

--reload는 permanent 설정 전체를 runtime에 다시 적용합니다. 이 한 줄을 빠뜨리면 “지금은 안 되는데 재부팅하면 되는” 묘한 상태가 됩니다. 채점 스크립트가 재부팅 없이 검사하면 실패할 수 있으므로, --permanent로 저장한 뒤 반드시 --reload 하는 습관을 들이겠습니다.

함정: –permanent를 빠뜨리는 실수 #

시험에서 시간에 쫓기면 무심코 다음처럼 칩니다.

# 흔한 실수. runtime에만 적용되어 재부팅 후 사라진다
firewall-cmd --add-service=https

이 명령은 출력이 success라서 성공한 것처럼 보입니다. 하지만 재부팅하면 규칙이 사라지므로 채점에서 0점입니다. “firewall에서 무언가를 허용하라"는 문제를 보면 반사적으로 --permanent를 먼저 떠올리는 것이 안전합니다. 안전한 표준 절차는 다음과 같습니다.

# 영구 + 즉시 적용을 한 세트로
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload

규칙 확인: –list-all #

작업 후에는 반드시 결과를 확인합니다. zone에 실제로 적용된 규칙을 한눈에 보는 명령이 --list-all입니다.

# 기본 zone(보통 public)의 runtime 규칙 전체 확인
firewall-cmd --list-all

# 특정 zone을 지정해서 확인
firewall-cmd --zone=public --list-all

출력은 다음과 비슷합니다.

public (active)
  target: default
  interfaces: ens160
  sources:
  services: ssh dhcpv6-client http https
  ports: 8080/tcp
  ...

여기서 servicesports 줄을 보고 의도한 규칙이 들어갔는지 확인합니다. 주의할 점은 --list-all이 기본적으로 runtime을 보여 준다는 것입니다. 영구 설정이 제대로 저장됐는지까지 확인하려면 --permanent를 함께 붙입니다.

# 영구 설정에 저장된 규칙 확인
firewall-cmd --permanent --list-all

runtime과 permanent가 둘 다 의도대로 나오면 그 작업은 완전히 끝난 것입니다.

rich rule: 세밀한 규칙 한 줄 #

단순 허용을 넘어 “특정 출발지에서 온 특정 서비스만 허용"처럼 조건을 세밀하게 거는 것이 rich rule입니다. RHCSA에서 깊게 묻지는 않지만, 한 줄 형태는 익혀 두면 유용합니다.

# 192.168.10.0/24 대역에서 오는 http만 영구 허용
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" service name="http" accept'
firewall-cmd --reload

rich rule도 다른 규칙과 똑같이 --permanent--reload가 필요합니다. 등록된 rich rule은 다음으로 확인합니다.

firewall-cmd --list-rich-rules

source로 zone 지정하기 #

zone에 인터페이스 대신 출발지 주소를 묶을 수도 있습니다. “이 주소에서 오는 트래픽은 더 신뢰하는 zone으로 처리하라” 같은 문제에 쓰입니다.

# 192.168.20.0/24 대역을 trusted zone으로 묶어 영구 적용
firewall-cmd --permanent --zone=trusted --add-source=192.168.20.0/24
firewall-cmd --reload

# 결과 확인. trusted zone의 sources 줄에 대역이 나타난다
firewall-cmd --zone=trusted --list-all

이렇게 하면 해당 대역에서 오는 트래픽은 public이 아니라 trusted zone 규칙을 따릅니다. source를 추가하면 그 zone이 active zone 목록에 나타나므로, --get-active-zones로도 확인할 수 있습니다.

SSH 키 인증 #

이제 두 번째 축입니다. SSH 키 인증은 비밀번호 대신 키 쌍(공개 키 + 개인 키) 으로 신원을 증명하는 방식입니다. 개인 키는 클라이언트가 가지고 있고, 공개 키를 서버에 등록해 두면 비밀번호 없이 로그인할 수 있습니다. 비밀번호 추측 공격에 강하고 자동화에 유리해 실무 표준입니다.

흐름은 세 단계입니다. 키를 만들고(ssh-keygen), 서버에 공개 키를 등록하고(ssh-copy-id), 권한을 맞춥니다.

1) 키 쌍 생성: ssh-keygen #

클라이언트(접속하는 쪽)에서 키 쌍을 만듭니다.

# RSA 키 쌍 생성 (기본 위치 ~/.ssh/에 저장)
ssh-keygen

# 옵션을 명시하는 형태. 타입과 주석 지정
ssh-keygen -t rsa -b 4096 -C "user@workstation"

ssh-keygen을 실행하면 저장 위치(~/.ssh/id_rsa)와 passphrase를 묻습니다. 기본값으로 진행하면 두 개의 파일이 생깁니다.

파일역할
~/.ssh/id_rsa개인 키. 절대 외부에 노출하면 안 됨
~/.ssh/id_rsa.pub공개 키. 서버에 등록하는 파일

passphrase는 개인 키 자체에 거는 추가 암호입니다. 보안에는 좋지만, 시험에서 비밀번호 없는 자동 로그인을 요구하면 passphrase를 비워 둡니다.

2) 공개 키 등록: ssh-copy-id #

만든 공개 키를 서버에 등록하는 가장 쉬운 방법이 ssh-copy-id입니다. 이 명령은 공개 키를 서버의 ~/.ssh/authorized_keys에 추가하고 권한까지 알아서 맞춰 줍니다.

# 서버 user 계정에 공개 키 등록 (이때 한 번은 비밀번호로 인증)
ssh-copy-id user@server

이 명령을 한 번 실행한 뒤부터는 비밀번호 없이 키로 로그인됩니다.

# 키 인증으로 접속. 비밀번호를 묻지 않으면 성공
ssh user@server

3) 수동 등록과 권한: authorized_keys #

ssh-copy-id를 쓸 수 없는 환경이면 공개 키를 직접 authorized_keys에 넣어야 합니다. 이때 권한을 정확히 맞추는 것이 핵심입니다. SSH는 권한이 느슨하면 보안상 키 인증을 거부합니다.

# 서버에서 대상 사용자로 작업한다고 가정
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# 공개 키 내용을 authorized_keys에 추가
cat id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

권한 규칙은 외워 두는 것이 좋습니다.

대상권한
~/.ssh 디렉터리700 (drwx——)
~/.ssh/authorized_keys 파일600 (-rw——-)
홈 디렉터리 자체그룹,기타에 쓰기 권한 없음

소유자도 중요합니다. 사용자의 .ssh 디렉터리와 그 안의 파일은 해당 사용자 소유여야 합니다. root로 다른 사용자의 키를 만들었다면 chown -R user:user /home/user/.ssh로 소유권을 맞추겠습니다. 키 인증이 안 될 때 가장 흔한 원인이 권한과 소유권이므로, 안 되면 여기부터 점검합니다. SELinux가 켜진 시스템에서는 컨텍스트도 영향을 주는데, 이는 #13 SELinux 깊이에서 restorecon으로 다루겠습니다.

4) 비밀번호 인증 끄기 (sshd 설정) #

키 인증을 강제하고 비밀번호 로그인을 막으려면 sshd 설정을 바꿉니다. 핵심은 다음 한 줄입니다.

# /etc/ssh/sshd_config 또는 /etc/ssh/sshd_config.d/*.conf에서 설정
PasswordAuthentication no

RHEL 9에서는 /etc/ssh/sshd_config.d/ 아래의 drop-in 파일이 메인 설정보다 우선하는 경우가 많으므로, 그쪽에 같은 키가 있는지도 확인하겠습니다. 설정을 바꾼 뒤에는 sshd를 다시 시작해야 적용됩니다.

# 설정 적용을 위해 sshd 재시작
systemctl restart sshd

주의할 점은, 비밀번호 인증을 끄기 전에 키 인증이 실제로 동작하는지 먼저 확인하는 것입니다. 키가 안 되는 상태에서 비밀번호까지 막으면 자기 자신이 로그인하지 못하는 상황이 생깁니다.

시험 포인트 #

  • firewalld 작업은 --permanent로 저장하고 --reload로 적용하는 두 단계가 한 세트입니다. 하나라도 빠지면 실점합니다.
  • “firewall에서 허용하라"는 문제를 보면 반사적으로 --permanent를 떠올립니다. runtime만 적용하면 재부팅 후 사라져 0점입니다.
  • 서비스는 --add-service=이름, 포트는 --add-port=포트/프로토콜 형식입니다. 포트에는 프로토콜(tcp/udp)을 반드시 붙입니다.
  • 작업 후 firewall-cmd --list-all로 runtime을, firewall-cmd --permanent --list-all로 영구 설정을 둘 다 확인합니다.
  • 활성 zone과 인터페이스는 --get-active-zones로, 출발지 기반 zone 지정은 --add-source로 처리합니다.
  • SSH 키 인증은 ssh-keygen으로 만들고 ssh-copy-id로 등록하는 흐름이 가장 빠릅니다.
  • 수동 등록 시 권한이 핵심입니다. ~/.ssh700, authorized_keys600, 소유자는 해당 사용자여야 합니다.
  • 비밀번호 인증을 끄려면 PasswordAuthentication nosystemctl restart sshd까지 해야 적용됩니다. 끄기 전에 키 로그인이 되는지 먼저 확인합니다.

정리 #

이번 글에서 잡은 것:

  • firewalld. zone으로 신뢰 수준을 나누고, firewall-cmd로 서비스,포트를 허용합니다.
  • 영구 적용. --permanent로 저장하고 --reload로 즉시 적용하는 두 단계가 필수입니다.
  • 확인. --get-active-zones로 활성 zone을, --list-all로 적용 규칙을 확인합니다.
  • 세밀한 규칙. rich rule로 출발지,서비스 조건을 걸고, --add-source로 zone을 지정합니다.
  • SSH 키 인증. ssh-keygenssh-copy-id 흐름, 수동 등록 시 700/600 권한과 소유권을 맞춥니다.
  • 비밀번호 차단. PasswordAuthentication no 후 sshd 재시작. 키 로그인을 먼저 검증합니다.

firewalld와 SSH 키 인증은 명령 자체는 어렵지 않지만, 영구 적용과 권한이라는 함정이 점수를 가릅니다. 두 작업 모두 “재부팅 후에도 유지되는가"와 “권한이 정확한가"를 마지막에 자문하는 습관으로 마무리하겠습니다.

다음: SELinux 깊이 #

방화벽과 SSH로 외부 접근을 통제했다면, 시스템 내부에서 프로세스가 무엇을 할 수 있는지를 통제하는 것이 SELinux입니다. RHCSA에서 가장 까다롭다고 꼽히는 영역이지만, 패턴을 알면 점수원이 됩니다.

#13 SELinux 깊이: contexts, booleans, troubleshooting (audit2allow)에서는 파일 컨텍스트를 다루는 semanage fcontextrestorecon, 동작을 토글하는 boolean, 그리고 거부 로그를 읽어 정책을 만드는 audit2allow까지 직접 쳐 보며 SELinux 트러블슈팅을 정리하겠습니다.

X