콘텐츠로 이동

SELinux Port 설정 가이드 (Enforcing 기준)

SELinux가 Enforcing 모드일 때,
기본 포트(Well-known Port)가 아닌 포트를 사용하는 서비스에 대해
SELinux 정책 차원에서 무엇이 막히고, 왜 막히며, 무엇을 허용해야 하는지를 구조적으로 설명하는 문서임.

⚠️ 포트를 외부에 개방하는 방법을 설명하지 않는다.
SELinux 포트 설정은 접근 허용이 아니라 사용 권한 분류 및 프로세스 권한 제어에 관한 설정임. SELinux는 단순한 보안 옵션이 아니라, 프로세스·포트·파일·네트워크 행위를 강제적으로 분리하는 핵심 보안 계층임.


SELinux 기본 운영 기준 (Baseline)

이 섹션은 SELinux Port 설정 이전에 반드시 충족되어야 하는 운영 전제 조건을 정의함.
아래 기준이 충족되지 않으면 이후 Port / Boolean 설정은 의미 없거나 위험해짐.


SELinux 상태 확인

sudo getenforce
  • Enforcing → 정상 (운영 기준)
  • Permissive → 로그만 기록 (임시 진단용)
  • Disabled → ❌ 운영 서버 기준 위반

추가 확인:

sudo sestatus

확인 항목:

  • SELinux status: enabled
  • Current mode: enforcing
  • Policy from config file: enforcing
  • Loaded policy name: targeted

설정 파일 기준값

sudo cat /etc/selinux/config

운영 서버 기준값:

SELINUX=enforcing
SELINUXTYPE=targeted
  • permissive → enforcing 전환은 즉시 가능
  • disabled → enforcing 전환은 재부팅 필요

필수 패키지 (minimal 환경 기준)

SELinux 정책 분석 및 운영을 위해 다음 패키지가 필요함.

sudo dnf install -y \
  policycoreutils \
  policycoreutils-python-utils \
  setools-console \
  audit

SELinux 차단 로그 확인 루틴

차단 발생 여부 확인:

sudo ausearch -m AVC,USER_AVC -ts recent

당일 요약:

sudo ausearch -m AVC -ts today

해석 도구 (선택):

sudo dnf install -y setroubleshoot-server
sudo sealert -a /var/log/audit/audit.log

운영 원칙 (절대 규칙)

  • SELinux disable 금지
  • setenforce 0 상시 사용 금지
  • 차단 발생 시:
    • 원인 로그 확인
    • Port / Context / Boolean 최소 범위 조정
    • 필요 시 custom policy 작성

SELinux를 끄는 것은 해결이 아니라
운영 포기 선언에 가깝다.


0. 반드시 이해해야 할 개념 (가장 중요)

SELinux 설정은 firewalld(방화벽)와 완전히 다른 계층의 문제임.

구분 역할
firewalld 외부 네트워크에서 해당 포트로 접근 자체를 허용할지 결정
SELinux 어떤 프로세스 타입이 어떤 포트/자원에 접근해도 되는지 결정

즉,

firewalld는 “들어오게 할지”를 결정하고
SELinux는 “누가 쓰게 할지”를 결정함

semanage portsetsebool포트를 여는 명령이 아니라, 내부 보안 정책을 분류/완화하는 명령임.


1. SELinux 모드 확인 (Enforcing 전제)

SELinux가 Enforcing 모드일 때만 이 문서의 내용이 의미 있음.

sudo getenforce
  • Enforcing → 정책 적용됨 (설정 필요)
  • Permissive → 차단은 안 하지만 로그만 남김
  • Disabled → SELinux 미사용 (운영 기준 위반)

Enforcing 기준 운영 문서임.


2. SELinux 포트 관리 도구 설치

semanage 명령을 사용하기 위해 다음 패키지가 필요함.

sudo dnf install -y policycoreutils policycoreutils-python-utils setools-console audit

3. SSH 포트 등록 (ssh_port_t)

SSH 포트를 기본값(22) 외의 포트로 변경한 경우 반드시 SELinux에 해당 포트를 등록해야 함.

확인

sudo semanage port -l | grep -w [PORT]

설정

위 목록에서 없으면 -a 있으면 -m

sudo semanage port -a -t ssh_port_t -p tcp 22

ex)

PORT=22
sudo semanage port -l | grep -w "$PORT"
sudo semanage port -a -t ssh_port_t -p tcp "$PORT" 2>/dev/null || sudo semanage port -m -t ssh_port_t -p tcp "$PORT"

⚠️ 이 설정은 firewalld와 무관
방화벽이 막혀 있으면 여전히 접근 불가


4. 기타 서비스 Port 등록 예시

서비스 성격에 맞는 SELinux 타입(Type) 을 사용해야 함.

4.1 HTTP / HTTPS 서비스 (Nginx, Apache 등)

확인

sudo semanage port -l | grep -w [PORT]

설정

위 목록에서 없으면 -a 있으면 -m

sudo semanage port -a -t http_port_t -p tcp 80
sudo semanage port -a -t http_port_t -p tcp 443

ex)

PORT=80
sudo semanage port -l | grep -w "$PORT"
sudo semanage port -a -t http_port_t -p tcp "$PORT" 2>/dev/null || sudo semanage port -m -t http_port_t -p tcp "$PORT"

4.2 MySQL (3306)

확인

sudo semanage port -l | grep -w [PORT]

설정

위 목록에서 없으면 -a 있으면 -m

sudo semanage port -a -t mysqld_port_t -p tcp 3306

ex)

PORT=3306
sudo semanage port -l | grep -w "$PORT"
sudo semanage port -a -t mysqld_port_t -p tcp "$PORT" 2>/dev/null || sudo semanage port -m -t mysqld_port_t -p tcp "$PORT"

4.3 (참고) 포트 등록이 아닌 Boolean 방식도 존재함

SELinux에서 접근 문제가 발생할 때 해결책은 2가지 축이 있음.

  • semanage port
    → 특정 포트를 특정 타입(http_port_t, ssh_port_t 등)으로 분류하는 방식

  • setsebool
    → 특정 도메인(httpd_t)의 동작을 Boolean으로 허용하는 방식

예: Nginx(httpd_t)가 내부 백엔드로 proxy_pass 시 connect가 막히는 경우, 다음 Boolean이 해결책이 될 수 있음.

sudo setsebool -P httpd_can_network_connect 1

단, 이 방식은 허용 범위가 넓으므로 서버 성격에 맞게 사용.


5. Node.js / Next.js / Custom Application 포트 설정 (중요)

Node.js / Next.js 는 전용 SELinux 타입이 존재하지 않음.
따라서 Nginx(httpd_t)가 내부적으로 접근해야 하는 경우에 한해
http_port_t 타입을 사용함.

확인

sudo semanage port -l | grep -w [PORT]

설정

위 목록에서 없으면 -a 있으면 -m

sudo semanage port -a -t http_port_t -p tcp 3000
sudo semanage port -a -t http_port_t -p tcp 3001
sudo semanage port -a -t http_port_t -p tcp 3002

ex)

PORT=3000
sudo semanage port -l | grep -w "$PORT"
sudo semanage port -a -t http_port_t -p tcp "$PORT" 2>/dev/null || sudo semanage port -m -t http_port_t -p tcp "$PORT"

❗ http_port_t 설정의 정확한 의미

이 설정은 다음을 의미함.

“httpd_t (Nginx)가 TCP 3000 포트로 연결(connect) 하는 것을 SELinux 정책 차원에서 허용한다” 해당 포트를 SELinux 정책상 httpd_t 도메인이 사용할 수 있는 포트로 등록함.

즉,

  • Nginx가 해당 포트로 bind 하거나
  • 해당 포트로 connect 하는 경우

SELinux 정책 차원에서 허용함.

⚠ 단, 일반적인 Nginx reverse proxy 구조에서는 대부분 httpd_can_network_connect boolean 설정으로 충분함.

Node가 3000 포트를 bind 하는 것과는 직접적인 관계 없음.

❌ 의미하지 않는 것:

  • Node.js / Next.js 포트를 외부에 개방 ❌
  • firewall-cmd로 포트를 여는 것 ❌
  • Node.js / Next.js 가 직접 인터넷을 받는 것 ❌

6. Node.js / Next.js 포트 설정이 필요한 경우 / 불필요한 경우

✅ 설정이 의미 있는 경우 (허용)

다음 조건이 모두 만족될 때만 의미 있음.

  • Node.js / Next.js 가 127.0.0.1:3000 에서만 listen
  • firewalld에서 3000 포트를 열지 않음
  • Nginx가 같은 서버에서 다음과 같이 프록시
proxy_pass http://127.0.0.1:3000;
  • SELinux Enforcing 상태
  • Nginx(httpd_t)가 3000 포트로 connect 해야 함

👉 이 경우 SELinux가 연결을 차단할 수 있으므로
👉 semanage port -a -t http_port_t -p tcp 3000필요할 수 있음

❌ 설정이 잘못된 경우 (금지)

다음 중 하나라도 해당하면 운영 기준 위반임.

  • Node.js / Next.js 가 0.0.0.0:3000 에서 listen
  • firewalld에서 3000 포트를 외부에 개방
  • “Node.js / Next.js 쓰니까 포트 등록해야 한다”는 이유로 설정

이 경우 문제는 SELinux가 아니라 네트워크 설계 자체임.


7. 등록된 포트 확인

대표적인 SELinux 포트 타입 정리

1. 웹(Web) 계열

포트 타입 설명 기본 포트 예시
http_port_t HTTP / HTTPS 서비스 80, 443
http_cache_port_t 프록시 / 캐시 서버 8080 등
http_alt_port_t 대체 HTTP 포트 8008, 8009 등

2. 데이터베이스(DB) 계열

포트 타입 설명 기본 포트 예시
mysqld_port_t MySQL / MariaDB 3306
postgresql_port_t PostgreSQL 5432
mongodb_port_t MongoDB 27017
redis_port_t Redis 6379

3. 메일(Mail) 계열

포트 타입 설명 기본 포트 예시
smtp_port_t SMTP 25
pop_port_t POP3 110
imap_port_t IMAP 143

4. 원격 접속 / 관리

포트 타입 설명 기본 포트 예시
ssh_port_t SSH 22
telnet_port_t Telnet 23
vnc_port_t VNC 5900
rdp_port_t RDP 3389

5. 기타 네트워크 서비스

포트 타입 설명 기본 포트 예시
dns_port_t DNS 53
ntp_port_t NTP 123
snmp_port_t SNMP 161
rpc_port_t RPC 111
ftp_port_t FTP 21
squid_port_t Squid Proxy 3128

확인

sudo semanage port -l | grep -w [PORT]

예를 들어 - -w 옵션이 없으면 포함된 것. ex) 221, 2202, 2222 - -w 옵션이 있으면 일치하는 것. ex) 22

또는

SSH 포트 확인

sudo semanage port -l | grep ssh_port_t

HTTP 계열 포트 확인

sudo semanage port -l | grep http_port_t

MySQL 포트 확인

sudo semanage port -l | grep mysqld_port_t

등.


8. 운영 기준 요약 (핵심)

  • SELinux 포트 설정은 접근 허용이 아님
  • firewalld와 절대 동일시하지 말 것
  • Node.js / Next.js 포트 외부 노출은 여전히 금지
  • 이 설정은 Nginx ↔ Node 내부 통신 보조용

SELinux 설정을 이해하지 못한 상태에서
포트부터 등록하는 순간
보안 사고의 씨앗이 심어진다.


9. Nginx upstream(proxy_pass) 50X 에러와 SELinux Boolean (실전 보완)

다음과 같은 상황에서 Nginx → upstream(http://127.0.0.1:[PORT]) 연결이 실패하며
502 Bad Gateway 또는 504 Gateway Timeout 이 발생하는 경우가 있음.

전형적인 증상

  • Nginx 정상 기동
  • Node.js / Next.js 정상 기동
  • 브라우저 접속 시 50X 에러
  • Nginx error.log 에 upstream connect 관련 에러 기록

이 경우 firewalld 문제가 아니라 SELinux 정책 차단일 가능성이 매우 높음.

9.1 httpd_can_network_connect (가장 대표적인 해결책)

sudo setsebool -P httpd_can_network_connect 1

의미

  • httpd_t(Nginx, Apache)가 로컬/내부 네트워크 포트로 connect 하는 행위 자체를 허용

언제 필요한가

  • proxy_pass http://127.0.0.1:[PORT]
  • 내부 API, 백엔드 서비스로 프록시 역할 수행
  • 포트가 고정되지 않거나 다수일 경우

⚠️ 허용 범위가 넓으므로
Gateway / Reverse Proxy 성격의 서버에서만 사용 권장 기본값은 OFF 유지

9.2 httpd_can_network_relay (중계 역할 허용)

sudo setsebool -P httpd_can_network_relay 1

의미

  • httpd(Nginx)가 네트워크 트래픽을 중계(relay) 하는 역할을 수행하도록 허용

언제 필요한가

  • Nginx가 단순 웹서버가 아니라
    • Reverse Proxy
    • API Gateway
    • 내부 서비스 중계 역할을 수행하는 경우

일반적인 단일 proxy_pass 구조에서는 반드시 필요한 경우에만 사용 기본값은 OFF 유지


10. 기타 httpd 관련 Boolean (운영 주의)

아래 설정들은 특정 요구사항이 있을 때만 사용해야 하며, 무분별한 활성화는 보안 모델을 약화시킴.

10.1 DB 네트워크 연결 허용

sudo setsebool -P httpd_can_network_connect_db 1
  • httpd 프로세스가 DB로 직접 네트워크 연결을 해야 하는 경우
  • 일반적인 Nginx → Node.js / Next.js → DB 구조에서는 불필요

10.2 익명 쓰기 권한 관련 (⚠️ 매우 위험)

sudo setsebool -P allow_httpd_anon_write 1
sudo setsebool -P allow_httpd_sys_script_anon_write 1

의미

  • 웹 서버 디렉터리에 익명 쓰기 권한 허용
  • 시스템 스크립트에 대한 쓰기 허용

운영 기준

❌ 일반적인 운영 서버에서는 사용 금지
❌ 임시 테스트 후 반드시 원복
❌ 보안 감사 시 즉시 지적 대상


11. 파일 컨텍스트 설정 (포트 문제와 별개)

Nginx가 특정 디렉터리에 대해 읽기/쓰기 권한필요한 경우 : httpd_sys_rw_content_t ex) uploads 읽기 전용 권한필요한 경우 : httpd_sys_content_t ex) public

확인

sudo semanage fcontext -l | grep /var/www/[ProjectName]

설정

위 목록에서 없으면 -a 있으면 -m

ex)

없을때

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/[ProjectName]/uploads(/.*)?"
sudo restorecon -Rv /var/www/[ProjectName]/uploads

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/[ProjectName]/public(/.*)?"
sudo restorecon -Rv /var/www/[ProjectName]/public

있을때

sudo semanage fcontext -m -t httpd_sys_rw_content_t "/var/www/[ProjectName]/uploads(/.*)?"
sudo restorecon -Rv /var/www/[ProjectName]/uploads

sudo semanage fcontext -m -t httpd_sys_content_t "/var/www/[ProjectName]/public(/.*)?"
sudo restorecon -Rv /var/www/[ProjectName]/public

ex)

PROJECT="ProjectName"
PROJECT_ROOT="/var/www/${PROJECT}"
FOLDER="${PROJECT_ROOT}/uploads"
PATTERN="(/.*)?"

sudo semanage fcontext -a -t httpd_sys_rw_content_t "${FOLDER}${PATTERN}" 2>/dev/null || sudo semanage fcontext -m -t httpd_sys_rw_content_t "${FOLDER}${PATTERN}"
sudo restorecon -Rv "${FOLDER}"

sudo semanage fcontext -l | grep "^${FOLDER}(\s|$)"

PROJECT="ProjectName"
PROJECT_ROOT="/var/www/${PROJECT}"
FOLDER="${PROJECT_ROOT}/public"
PATTERN="(/.*)?"

sudo semanage fcontext -a -t httpd_sys_content_t "${FOLDER}${PATTERN}" 2>/dev/null || sudo semanage fcontext -m -t httpd_sys_content_t "${FOLDER}${PATTERN}"
sudo restorecon -Rv "${FOLDER}"

sudo semanage fcontext -l | grep "^${FOLDER}(\s|$)"
  • 이는 파일 접근 권한 문제
  • proxy_pass / 포트 차단 문제와는 완전히 다른 영역

12. 설정 확인 명령 (문제 해결 후 반드시 확인)

Boolean 확인

sudo getsebool -a | grep httpd_can_network_connect
sudo getsebool -a | grep httpd

포트 타입 확인

sudo semanage port -l | grep http_port_t

위 목록에서 없으면 -a 있으면 -m


13. 재부팅에 대한 정리

  • semanage port -a 또는 semanage port -m → 영구 적용
  • setsebool -P → 영구 적용
  • 대부분의 경우 reboot 불필요
  • 필요 시:
    • systemctl restart nginx
    • audit 로그 재확인

14. 최후의 방법 (운영 기준상 ❌ 금지)

sudo setenforce 0

또는

# /etc/selinux/config
SELINUX=disabled

왜 금지인가

  • 문제 원인 은폐
  • 보안 정책 완전 포기
  • 동일 문제 재발 확정

SELinux를 끄는 순간
우리는 왜 방화벽을 쓰는가?”라는 질문도 의미를 잃는다


15. 추가 요약 (기존 요약 보완)

  • semanage port
    포트 단위 최소 권한
  • setsebool
    프로세스 권한 완화
  • 50X 에러의 상당수는 SELinux 내부 차단
  • Disabled는 해결책이 아니라 운영 실패 선언

이해 없이 Boolean부터 켜는 순간
보안은 이미 무너진 상태다.