대상 OS: Rocky Linux 9

SELinux를 끄는 순간, “한 번 뚫리면 어디까지 번지는가”에 대한 마지막 방어막이 사라집니다.
그런데 웹 서버나 리버스 프록시를 운영하다 보면 포트 바꾸기, 백엔드로 프록시 패스하기, 소켓/파일 접근 때문에 SELinux 경고가 쌓이고 결국 Permissive/Disabled로 도망가기 쉽습니다.
오늘은 Rocky Linux 9에서 NGINX 리버스 프록시를 SELinux Enforcing 상태로 유지하면서도 운영이 가능하도록, (1) 정석적인 허용(booleans/port label), (2) 로그 기반 원인 분석(audit), (3) 최소 권한 커스텀 정책 만들기까지 한 흐름으로 정리합니다.
특히 “왜 막히는지”를 이해하는 절차를 넣어, 다음번에 비슷한 이슈가 나와도 스스로 해결할 수 있게 만드는 게 목표입니다.
이 글의 예시는 NGINX 기준이지만, Apache/커스텀 데몬에도 거의 동일한 방식으로 적용할 수 있습니다.

---

# 1) 먼저 확인: SELinux 상태와 정책 타입 점검

1) 현재 SELinux가 켜져 있는지 확인

getenforce
sestatus

2) 부팅 후에도 Enforcing으로 유지되는지 확인

cat /etc/selinux/config

- Rocky 9의 기본은 보통 `SELINUX=enforcing`, `SELINUXTYPE=targeted`입니다.
- `targeted`는 “중요 서비스(도메인)” 중심으로 통제하는 형태라 서버 운영에서 현실적인 균형점입니다.

---

# 2) NGINX 설치 및 기본 동작 확인(SELinux 문제 분리)

1) NGINX 설치/기동

sudo dnf install -y nginx policycoreutils-python-utils setroubleshoot-server
sudo systemctl enable --now nginx

2) 서비스 상태/리스닝 포트 확인

sudo systemctl --no-pager -l status nginx | sed -n '1,40p'
ss -lntp | grep nginx || true

- 이 단계에서 기본 80/443은 대개 SELinux 이슈 없이 동작합니다.
- 이후부터는 “변경 사항(포트/프록시/파일)”을 넣으면서 막히는 지점을 찾아 해결합니다.

---

# 3) 실무 1: NGINX를 ‘기본 포트가 아닌 곳’에서 띄우기(포트 레이블)

1) 문제 패턴

- 예: 8080/8443/18080 같은 커스텀 포트로 NGINX를 띄우면, 설정은 맞는데 바인딩이 실패하거나 접속이 안 됩니다.
- SELinux는 포트에 “어떤 서비스가 써도 되는지” 라벨(타입)을 붙여 통제합니다.

2) 현재 http 포트 라벨 확인

sudo semanage port -l | grep -E '^http_port_t\b' | head -n 20

3) 커스텀 포트를 http_port_t로 라벨링

- 아래는 예시로 8080/tcp를 NGINX가 쓸 수 있게 허용합니다.

sudo semanage port -a -t http_port_t -p tcp 8080 2>/dev/null || sudo semanage port -m -t http_port_t -p tcp 8080
sudo semanage port -l | grep -E '^http_port_t\b' | grep 8080 || true

4) NGINX 리스닝을 8080으로 변경 후 재기동

sudo sed -i 's/listen\s\+80;/listen 8080;/' /etc/nginx/nginx.conf
sudo nginx -t
sudo systemctl restart nginx
ss -lntp | grep ':8080' || true

---

# 4) 실무 2: 리버스 프록시에서 “백엔드로 나가는 연결”이 막힐 때(SELinux boolean)

1) 문제 패턴

- `proxy_pass http://127.0.0.1:9000;` 또는 내부망 백엔드로 붙였는데 502가 나거나 connect() denied
- 방화벽/라우팅은 정상이지만 SELinux가 “웹 서버 도메인이 외부로 네트워크 연결하는 것”을 제한

2) 핵심 boolean: httpd_can_network_connect

- NGINX는 SELinux에서 httpd 계열 도메인으로 분류되며, 이 boolean이 대표적으로 필요합니다.

sudo getsebool -a | grep -E '^httpd_can_network_connect\b'

3) 영구 활성화(재부팅 후에도 유지)

sudo setsebool -P httpd_can_network_connect on
sudo getsebool httpd_can_network_connect

4) 동작 확인을 위한 간단한 백엔드 예시(로컬 9000)

- 운영 서버에서는 이미 백엔드가 있겠지만, 원인 분리를 위해 “테스트 백엔드”를 띄우는 게 도움이 됩니다.

sudo bash -lc 'cat >/etc/nginx/conf.d/proxy-test.conf