SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor

Rocky Linux SSH 포트 변경 방법: SELinux 및 firewalld 설정

Rocky Linux와 AlmaLinux에서 SSH 포트를 안전하게 변경하는 방법을 설명합니다. firewalld 규칙 추가와 semanage를 이용한 SELinux 포트 레이블 설정, sshd_config 수정까지 세션 끊김 없이 적용하는 정확한 절차를 확인하십시오.

SSH 포트 변경 시 세 단계가 필요한 이유

Rocky Linux, AlmaLinux, CentOS Stream 또는 Fedora에서 SSH 포트를 변경할 때는 설정 파일 수정만으로는 부족합니다. 새로운 포트에서 연결이 정상적으로 작동하려면 세 가지 시스템의 설정을 모두 확인해야 합니다. firewalld는 패킷이 서버에 도달할 수 있는지 결정합니다. SELinux는 sshd이 해당 포트 번호에 바인딩할 수 있는지 결정합니다. sshd_config은 데몬이 사용할 포트를 결정합니다. SELinux 단계를 생략하면 데몬이 시작되지 않습니다. firewalld 단계를 생략하면 데몬은 시작되어 포트를 점유하지만, 외부에서 접근할 수 없습니다.

Ubuntu에서는 설정 파일 수정 후 재시작만 하면 되는데, 이는 Ubuntu가 SELinux 대신 AppArmor를 사용하며 sshd가 바인딩할 수 있는 포트를 제한하는 프로필을 기본적으로 제공하지 않기 때문입니다. ufw가 실행 중이라면 규칙 하나만 추가하면 됩니다. 이것이 두 운영체제 계열의 차이점입니다. RHEL 계열은 초기 설치 시 firewalld가 실행 중이고 SELinux가 enforcing 모드로 동작하므로, 두 시스템 모두 포트 번호를 엄격하게 관리합니다.

다음 순서대로 작업을 진행하면 현재 세션을 유지하면서 안전하게 변경할 수 있습니다.

  1. firewalld에서 새 포트를 개방하고, 기존 22번 포트는 당분간 그대로 둡니다.
  2. semanage을 사용하여 새 포트에 SELinux 레이블을 추가합니다.
  3. sshd 설정에서 포트를 변경합니다.
  4. sshd를 재시작한 뒤, 첫 번째 터미널을 닫기 전에 두 번째 터미널에서 새 포트로 로그인을 시도합니다.
작업을 시작하기 전에 제공업체의 웹 콘솔(VNC 또는 시리얼) 접속 방법을 확인하고, 로그인이 가능한지 점검하십시오. 설정 변경에 실패했을 때 서버에 다시 접속할 수 있는 유일한 수단입니다. 포트 변경은 사용자가 새로 대여한 서버에서 스스로 접속을 차단하게 되는 가장 흔한 원인 중 하나입니다.

먼저 semanage를 설치합니다

semanage은 SELinux 정책 설정을 편집하는 도구이며, Rocky Linux나 AlmaLinux를 최소 설치하면 이 도구가 포함되지 않습니다. 이 도구는 policycoreutils-python-utils 패키지에 들어 있습니다.

sudo dnf install -y policycoreutils-python-utils

해당 패키지를 설치하기 전에 명령어를 실행하면 sudo: semanage: command not found 오류가 발생합니다. 많은 사용자가 이 시점에서 SELinux가 설치되지 않았다고 판단하고 단계를 건너뜁니다. SELinux는 설치되어 있습니다. 단지 관리 도구만 누락된 상태입니다. dnf 구문이 생소하다면, dnf 및 apt 명령어 대응표를 통해 이미 알고 있는 명령어와 비교해 보십시오.

포트를 선택하고 해당 포트를 점유 중인 프로세스가 없는지 확인하기

1024에서 65535 사이의 사용 가능한 TCP 포트라면 무엇이든 좋습니다. 포트를 결정하기 전에 다음 두 가지를 확인하십시오.

sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222

첫 번째 명령은 해당 포트 번호에서 이미 수신 대기 중인 프로세스가 있는지 보여줍니다. 두 번째 명령은 SELinux 정책이 해당 포트를 다른 서비스 유형에 이미 할당했는지 확인합니다. 사용 가능한 포트라면 두 명령 모두 아무런 결과도 출력하지 않습니다. 정책이 이미 해당 포트를 점유하고 있다면 2단계의 semanage port -a 명령이 ValueError: Port tcp/2222 already defined 오류와 함께 실패하며, 이 경우 다른 포트 번호를 선택해야 합니다.

이 가이드에서는 예시로 2222 포트를 사용합니다. 2222는 스캐너가 22 포트 다음으로 가장 먼저 시도하는 포트이므로, 실제 서버에서는 더 예측하기 어려운 포트를 선택하십시오.

1단계: firewalld에서 포트 열기

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

--permanent은(는) 규칙을 디스크의 영역 파일에 기록하며 실행 중인 방화벽에는 영향을 주지 않습니다. --reload은(는) 디스크의 설정을 실행 중인 방화벽으로 불러옵니다. reload를 건너뛰면 규칙은 존재하지만 다음 firewalld 재시작 전까지는 아무런 동작을 하지 않으며, 이는 전체 과정이 이유 없이 실패한 것처럼 보이는 가장 흔한 원인 중 하나입니다.

ssh 서비스 항목은 당분간 그대로 두십시오. 해당 항목은 포트 22를 열어두는 역할을 하며, 테스트 중 문제가 발생할 경우를 대비한 안전장치입니다.

제공업체의 제어판도 확인하십시오. 많은 호스트가 운영체제 외부인 VPS 앞단에서 네트워크 방화벽을 운영하므로, firewalld에서 포트를 열었더라도 상위 네트워크에서 차단될 수 있습니다. VPS를 위한 firewalld 기초 가이드에서 영역(zone) 개념과 런타임 및 영구 설정의 차이를 다루고 있으니, 해당 모델이 생소하다면 참고하십시오.

2단계: SELinux용 포트 레이블 지정

sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t

-a 명령은 새로운 포트 할당을 추가합니다. -t ssh_port_t은 SSH 포트가 사용하는 유형입니다. 두 번째 명령은 현재 ssh_port_t이 적용된 모든 항목을 나열하므로, 데몬을 수정하기 전에 포트 번호가 정상적으로 등록되었는지 확인할 수 있습니다.

SELinux가 포트를 차단하는 이유

SELinux(Security-Enhanced Linux)는 시스템의 모든 객체에 레이블을 부여하며, TCP 포트 번호 역시 다른 객체와 마찬가지로 레이블이 지정됩니다. SSH 데몬은 sshd_t라는 도메인 내에서 제한된 상태로 실행됩니다. 정책상 sshd_tssh_port_t 레이블이 지정된 TCP 포트에만 바인딩할 수 있으며, 기본 설정에서 이 레이블이 지정된 포트는 22번뿐입니다. 데몬에 2222번 포트 바인딩을 요청하면 커널은 레이블을 확인하고 해당 번호에 할당된 일반적인 정책 유형을 찾은 뒤, 소켓에 대한 name_bind 권한을 거부합니다.

이러한 이유로 이 오류는 방화벽 문제처럼 보이지 않습니다. 리스닝 소켓이 생성되기도 전에 커널이 거부하기 때문에, sshd은 오류를 보고하고 종료됩니다. 방화벽 문제는 이와 정반대입니다. 데몬은 정상적으로 실행 중이지만 들어오는 패킷이 도중에 폐기되는 상황입니다.

getenforce 명령을 사용하면 현재 시스템의 모드를 확인할 수 있습니다. Permissive 모드에서는 거부 기록만 남고 실제 차단은 수행되지 않으므로, 포트 변경이 정상적으로 작동하는 것처럼 보이다가 누군가 setenforce 1를 실행하거나 시스템이 Enforcing 모드로 재부팅될 때 문제가 발생합니다. 어떤 모드에서든 포트에 올바른 레이블을 지정해야 합니다. 서버를 위한 SELinux 기초 가이드에서 모드, 컨텍스트, 불리언(boolean)에 대해 자세히 다룹니다.

3단계: sshd 설정에서 포트 지정하기

Rocky Linux 9 및 10, AlmaLinux 9 및 10, 그리고 최신 Fedora에서는 /etc/ssh/sshd_config이 include 라인으로 시작하므로, 설정을 변경할 때는 드롭인(drop-in) 파일을 사용하는 것이 깔끔합니다. 이렇게 하면 패키지 업데이트 시 설정이 덮어씌워지지 않습니다.

grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -t

만약 grepInclude 라인이 없다면(Rocky Linux 8 및 기타 구형 이미지의 경우), Port 2222/etc/ssh/sshd_config에 직접 추가하십시오. sshd -t는 드롭인 파일을 포함한 전체 설정을 구문 분석하여 오류를 보고합니다. 구문 분석에 실패한 설정은 데몬이 재시작되지 않는 원인이 되므로, 재시작 전에 보고된 모든 오류를 수정해야 합니다.

Port은 여러 번 나타날 수 있으며, sshd는 나열된 모든 포트에서 수신 대기합니다. 첫날에는 Port 22Port 2222과 함께 유지하는 것이 저렴한 안전장치가 될 수 있습니다. 단, 나중에 반드시 제거해야 한다는 점을 기억하십시오.

sshd가 소켓 유닛으로 시작됩니까?

일부 이미지에서는 SSH를 상시 실행되는 서비스가 아닌 systemd 소켓 활성화를 통해 시작합니다. 이 방식이 설정된 경우, systemd가 리스닝 소켓을 소유하고 연결을 sshd로 전달하므로 sshd_configPort 줄은 완전히 무시됩니다. 무언가를 재시작하기 전에 다음을 확인하십시오.

systemctl is-enabled sshd.socket

enabled라는 응답이 나오면 포트가 sshd_config가 아닌 소켓 유닛에 설정된 것입니다.

sudo systemctl edit sshd.socket
[Socket]
ListenStream=
ListenStream=2222

ListenStream= 설정이 필요합니다. 값은 드롭인 파일 전체에 걸쳐 누적되므로, 먼저 빈 값으로 할당하여 목록을 비우지 않으면 소켓은 22번 포트와 2222번 포트 모두에서 계속 대기하게 됩니다. sudo systemctl daemon-reload를 사용하여 이를 적용한 뒤 sudo systemctl restart sshd.socket를 실행하십시오. 서버에 해당 유닛이 비활성화되어 있거나 존재하지 않는다면 이 섹션은 귀하에게 해당하지 않습니다.

단계 4: 재시작 후 두 번째 터미널에서 테스트

sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshd

현재 터미널을 그대로 유지하십시오. 로그아웃하지 마십시오. 로컬 머신에서 두 번째 터미널을 열고 새로운 포트로 접속하십시오:

ssh -p 2222 youruser@203.0.113.10

두 번째 로그인까지 성공한 것을 확인한 뒤에 첫 번째 세션을 종료하십시오. 만약 접속이 되지 않는다면, 설정을 되돌릴 수 있는 셸이 여전히 활성화된 상태입니다. 이 습관 하나가 5분이면 끝날 작업을 콘솔 앞에서 오후 내내 매달리게 만드는 상황으로 바꾸지 않는 유일한 방법입니다.

방화벽 차단인가 SELinux 거부인가? 구분 방법

노트북에서 확인하면 두 장애는 거의 동일해 보이지만, 서버 내부에서는 완전히 다르게 나타납니다.

  • systemctl status sshd 명령으로 서비스가 실패한 것으로 나온다면, 데몬이 소켓을 할당받지 못한 것입니다. 이는 설정 오류이거나 SELinux 거부 때문입니다.
  • 서비스가 활성 상태이고 ss -tlnp 명령으로 sshd가 새 포트에 바인딩된 것이 확인된다면, 데몬은 정상입니다. 문제는 네트워크 경로에 있습니다. firewalld, 클라우드 제공업체의 별도 방화벽, 또는 접속 시도한 주소나 포트가 원인일 수 있습니다.

SELinux 문제라면 추측하지 말고 감사(audit) 기록을 확인하십시오:

sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pager

name_bind 거부 메시지의 tcp_socket 클래스에는 comm="sshd" 프로세스, src= 포트 번호, 그리고 tcontext= 필드에 해당 포트가 실제로 할당받은 레이블이 표시됩니다. 마지막 필드가 핵심입니다. ssh_port_t 이외의 값이 있다면 2단계 작업이 해당 포트에 적용되지 않은 것입니다. 보통 포트 번호 오타나 잘못된 프로토콜 설정이 원인입니다. sealert 도구를 사용하여 기록을 읽기 쉬운 문장으로 변환하고 싶다면 setroubleshoot-server 패키지를 설치하십시오.

커널이 바인딩을 거부할 때 sshd가 직접 기록하는 메시지는 다음과 같습니다:

error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.

루트 권한이 필요 없는 1024 이상의 포트에서 발생하는 Permission denied 오류는 SELinux의 전형적인 징후입니다. 같은 줄에 Address already in use이 표시된다면 다른 프로세스가 이미 해당 포트를 점유하고 있다는 뜻입니다. 클라이언트 측에서는 connection refused와 connection timed out의 차이를 통해 네트워크 문제를 구분할 수 있습니다. 연결 거부(refused)는 패킷이 호스트에 도달했으나 수신 대기 중인 서비스가 없음을 의미하고, 시간 초과(timeout)는 아무런 응답이 없음을 의미합니다.

포트 22를 닫고 클라이언트 업데이트하기

새로운 포트로 로그인이 여러 번 성공적으로 이루어졌다면, 포트 22를 닫습니다.

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

firewall-cmd --permanent --remove-service=ssh

firewall-cmd --reload

포트 22에 설정된 SELinux 레이블은 그대로 둡니다. 이는 기본 정책에서 제공하는 것이며, 방화벽이 패킷 유입을 차단하면 해당 레이블은 아무런 권한도 부여하지 않습니다.

그다음 클라이언트를 수정하십시오. 기본 포트를 사용한다고 가정했던 모든 도구에 변경 사항을 알려야 합니다. 매번 -p를 입력하는 대신, 본인 컴퓨터의 ~/.ssh/config에 한 번만 설정해 두십시오.

Host myvps
  HostName 203.0.113.10
  Port 2222
  User youruser

Host example
HostName 1.2.3.4
Port 2222

scp, sftp, rsync 및 Ansible은 모두 해당 파일을 읽습니다. 포트 22를 하드코딩한 백업 작업, 모니터링 체크, cron 스크립트는 이 파일을 참조하지 않으므로, 변경 사항이 기억에 생생할 때 이들을 찾아 수정하십시오.

포트 변경이 주는 이점과 그렇지 않은 점

포트 변경은 로그 노이즈를 줄여줍니다. 자동화된 스캐너는 22번 포트를 끊임없이 공격하므로, 포트를 옮기면 저널에서 대부분의 관련 로그가 사라져 실제 이벤트를 확인하기가 더 쉬워집니다. 하지만 이는 보안 통제 수단이 아닙니다. 전체 포트 범위를 스캔하는 스캐너는 어떤 것이든 귀하의 데몬을 찾아내어 버전 배너를 읽어낼 것입니다. 포트 변경은 단순한 관리 작업으로 간주하십시오. 실제 보안은 비밀번호 로그인을 비활성화하고 키 기반 인증만 사용하는 것으로 구현해야 하며, 이에 대해서는 VPS를 위한 SSH 강화 가이드에서 단계별로 설명합니다.

위의 모든 내용은 두 주요 RHEL 리빌드 버전에서 동일하게 작동합니다. 두 배포판 모두 동일한 소스에서 빌드되기 때문입니다. 아직 배포판을 선택 중이라면 Rocky Linux와 AlmaLinux 비교를 참조하십시오. 오래된 가이드를 따르기 전에 cat /etc/os-release 명령으로 현재 사용 중인 릴리스 버전을 먼저 확인하십시오. Rocky Linux 8용으로 작성된 가이드는 여전히 검색 결과 상단에 노출되며 그 안의 semanagefirewall-cmd 단계는 여전히 정확합니다. 하지만 Rocky 8에는 sshd_config.d include 라인이나 고려해야 할 소켓 유닛이 없으므로, 해당 가이드의 sshd 관련 내용은 현재 시스템과 일치하지 않습니다.

fail2ban에 새로운 포트를 알려주어야 합니다

fail2ban은 기본 저장소에 포함되어 있지 않습니다. EPEL(Extra Packages for Enterprise Linux) 저장소에서 설치해야 합니다.

sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalld

fail2ban-firewalld 하위 패키지를 사용하면 fail2ban이 firewalld를 통해 차단 규칙을 적용합니다. firewalld가 규칙 집합을 관리하는 서버에서는 이 방식이 권장됩니다.

기본 sshd jail 설정은 port = ssh를 사용하며, 이 이름은 /etc/services을 통해 22번 포트로 해석됩니다. 포트를 변경한 후에는 jail이 아무도 공격하지 않는 포트를 감시하게 되므로, 2222번 포트에 로그인 실패가 쌓여도 아무도 차단하지 못합니다. /etc/fail2ban/jail.local 설정 파일에서 포트를 숫자로 직접 지정하십시오.

[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600

backend = systemd/var/log/secure 대신 journal에서 실패 기록을 읽어옵니다. rsyslog가 설치되지 않을 수 있는 최소 설치 환경에서는 이 방식이 더 안전합니다. sudo systemctl enable --now fail2ban 명령으로 서비스를 시작하고 sudo fail2ban-client status sshd 명령으로 jail 상태를 확인하십시오. jail 구문은 Ubuntu 24.04의 SSH용 fail2ban 설정에서 사용하는 것과 동일합니다. 패키지 소스와 차단 동작(ban action)만 다릅니다.

포트 변경보다 패치가 더 중요합니다

SSH 포트를 변경하고 4개월 동안 보안 업데이트를 적용하지 않은 서버는, 22번 포트를 사용하더라도 매일 밤 자동으로 패치되는 서버보다 보안 상태가 더 취약합니다. root 권한으로 작업하는 김에 같은 세션에서 자동 업데이트를 활성화하십시오. Rocky Linux 및 AlmaLinux에서 dnf 자동 업데이트 설정하기 문서에서 타이머 설정과 업데이트 다운로드 및 적용 방식 선택에 대해 다룹니다.

FAQ

Rocky Linux에서 포트를 변경한 후 sshd가 시작되지 않는 이유는 무엇입니까?

거의 대부분 SELinux 포트 레이블이 누락되었기 때문입니다. sshdsshd_t 도메인 내에서 제한된 상태로 실행되며, 정책상 ssh_port_t로 레이블이 지정된 포트만 바인딩할 수 있습니다. 기본적으로 이 레이블은 22번 포트에만 할당되어 있습니다. 커널이 바인딩을 거부하면 데몬은 리스닝을 시작하지 못하고 종료되며, journalctl -u sshd에는 error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. 형태의 메시지가 기록됩니다. 본인의 포트 번호를 사용하여 sudo semanage port -a -t ssh_port_t -p tcp 2222를 실행한 후 서비스를 재시작하십시오. semanage 명령을 찾을 수 없다면 policycoreutils-python-utils를 먼저 설치하십시오.

SELinux가 permissive 모드일 때도 semanage가 필요합니까?

네, 필요합니다. permissive 모드에서는 거부 기록만 남을 뿐 바인딩 자체는 허용되므로 설정이 정상적으로 작동하는 것처럼 보입니다. 하지만 레이블은 여전히 누락된 상태입니다. 누군가 setenforce 1를 실행하거나, /etc/selinux/config 파일에 SELINUX=enforcing을 설정하고 재부팅하는 순간 sshd는 해당 포트에서 시작되지 않습니다. 레이블을 추가하는 것은 명령어 한 줄이면 충분하며, 나중에 원인을 알 수 없는 장애가 발생하는 것을 방지할 수 있습니다.

포트 레이블도 지정했고 sshd도 실행 중인데 왜 연결 시간이 초과됩니까?

데몬이 실행 중이라면 SELinux 문제는 해결된 것이므로, 패킷이 들어오는 과정에서 차단되고 있는 것입니다. sudo firewall-cmd --list-ports 명령으로 포트 상태를 확인하고, --permanent 규칙을 추가한 뒤 firewall-cmd --reload를 실행했는지 확인하십시오. 영구 규칙만 추가해서는 현재 실행 중인 방화벽에 즉시 적용되지 않습니다. 그다음 VPS 앞단에 별도의 네트워크 방화벽이 있는지 호스트 제어판을 확인하십시오. 많은 사용자가 이 단계에서 차단되는데, 운영체제 내부에서는 이를 확인할 방법이 없습니다.

22번 포트 대신 어떤 포트를 사용해야 합니까?

1024에서 65535 사이의 사용 가능한 TCP 포트라면 무엇이든 좋습니다. 실제 운영 서버에서는 2222나 22222 포트를 피하십시오. 스캐너들이 22번 다음으로 가장 먼저 시도하는 포트이기 때문입니다. sudo ss -tlnp 명령으로 해당 번호가 비어 있는지 확인하고, sudo semanage port -l 명령으로 SELinux 정책이 이미 해당 포트를 점유하고 있지 않은지 확인하십시오. 나중에 설치할 서비스가 사용할 만한 포트 번호는 피하는 것이 좋습니다. 기억하기 어려운 높은 번호의 포트를 사용해도 괜찮습니다. ~/.ssh/config에 한 번만 기록해 두면 다시 입력할 일이 없기 때문입니다.