콘텐츠로 이동

Next.js 연동 구조와 SELinux Enforcing 동작 흐름

Next.js는 운영 환경에서 프론트엔드 서버 런타임(Node.js 프로세스) 으로 동작하며,
외부 트래픽의 진입점은 항상 Nginx가 담당함.

SELinux Enforcing 환경에서 Nginx의 proxy_pass가 Next.js로 정상 동작하기 위해
어떤 보안 검사가 수행되며, 왜 막히고, 무엇을 허용해야 하는지를 구조적으로 설명함.

설정 나열이 목적이 아님
“왜 이 설정이 필요한가”를 이해시키기 위한 문서


1. 기본 전제 (이 문서를 읽기 전 상태)

다음 조건을 전제로 설명함.

  • SELinux: Enforcing
  • Nginx: 정상 기동 (httpd_t)
  • Next.js: 정상 기동 (PM2, 127.0.0.1:3000 listen)
  • Firewall:
    • 80 / 443 만 외부 허용
    • 3000 포트 외부 미개방
  • Next.js 프론트엔드 서버는 외부 트래픽을 직접 받지 않음

2. 전체 트래픽 흐름 (정상 구조)

[ Client ]
    ↓
[ Nginx (httpd_t) ]
    ↓  proxy_pass
[ 127.0.0.1:3000 ]
    ↓
[ Next.js Frontend Server (PM2) ]

이 구조에서 외부에서 접근 가능한 것은 Nginx 뿐임.
Next.js 포트(예: 3000)는 내부 전용이며, 외부 노출 대상으로 취급하지 않음.


3. Firewall와 SELinux의 역할 차이 (가장 중요한 구분)

운영 사고의 상당수는 이 둘을 혼동하면서 발생함.

3.1 Firewall의 역할

항목 의미
기준 네트워크
판단 대상 패킷
질문 “외부에서 이 포트로 들어와도 되는가?”

외부 접근 제어 담당

3.2 SELinux의 역할

항목 의미
기준 프로세스
판단 대상 프로세스 ↔ 포트
질문 “이 프로세스가 이 포트로 connect 해도 되는가?”

내부 접근 제어 담당

핵심 정리

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


4. 왜 proxy_pass가 SELinux에서 막히는가?

Nginx는 SELinux에서 httpd_t 타입으로 실행됨.

SELinux는 다음 질문을 던짐:

httpd_t 프로세스가 tcp/3000 포트로 connect 해도 되는가?”

기본 정책의 현실

  • httpd_t → 80, 443 (허용)
  • httpd_t → 3000 (❌ 기본적으로 차단)

따라서 다음 현상이 발생할 수 있음.

  • Nginx는 정상 기동
  • proxy_pass 대상(127.0.0.1:3000) 연결만 실패
  • 결과는 502/504 형태로 표면화됨

5. semanage port의 진짜 의미 (오해 금지)

다음 명령은 접근 허용 명령이 아님.

추가

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

수정

sudo semanage port -m -t http_port_t -p tcp 3000

이 명령이 하는 일

“tcp/3000 포트는
http 계열 프로세스(httpd_t)가 connect 가능한 포트다
라고 SELinux에게 ‘포트 타입’으로 분류해준다”

하지 않는 일

  • 포트 개방 ❌ (firewalld 영역)
  • 외부 접근 허용 ❌ (firewalld 영역)
  • Next.js 보안 완화 ❌ (오히려 Enforcing 유지에 필요한 정리)

👉 “사용 권한 분류(포트 타입 지정)”일 뿐임


6. 언제 semanage port 설정이 필요한가? (조건 명확화)

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

✅ 의미 있는 경우 (권장 시나리오)

  • Next.js가 127.0.0.1:3000 에서만 listen
  • firewall에서 3000 포트 미개방
  • Nginx가 같은 서버에서 실행
  • proxy_pass http://127.0.0.1:3000
  • SELinux Enforcing
  • Nginx(httpd_t)가 내부적으로 3000에 connect 필요

👉 이 경우에만 아래 설정이 논리적으로 정확함.

추가

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

수정

sudo semanage port -m -t http_port_t -p tcp 3000

❌ 의미 없거나 위험한 경우 (금지/불필요)

  • Next.js 포트를 외부에 직접 열어둔 경우
  • Nginx 없이 Next.js 단독 서비스
  • SELinux Disabled / Permissive
  • “에러 나니까 일단 넣는” 경우

👉 이 접근은 보안 모델 붕괴로 이어질 가능성이 높음.


7. 자주 발생하는 잘못된 사고 흐름

❌ 잘못된 대응:

  1. proxy_pass 안 됨
  2. SELinux 로그 무시
  3. setenforce 0
  4. “SELinux는 쓰면 안 된다” 결론

⭕ 올바른 대응:

  1. proxy_pass 안 됨
  2. SELinux audit 로그 확인
  3. “httpd_t → tcp/3000 connect 차단” 인지
  4. semanage 또는 boolean으로 정책 허용
  5. Enforcing 유지

8. 운영 기준 요약

  • Next.js 포트는 외부에 열지 않음
  • semanage port포트 개방이 아님
  • proxy_pass 동작을 위한 SELinux 내부 권한 정리일 뿐
  • firewall / SELinux 역할을 혼동하지 않음

SELinux를 끄는 순간
“우리는 왜 Enforcing을 쓰는가?”라는 질문이 무의미해짐


9. 같은 카테고리의 다른 해결책: httpd_can_network_connect (Boolean)

SELinux Enforcing 환경에서 Nginx(httpd_t)의 proxy_pass가 막힐 때,
해결 방법은 크게 2가지 축으로 분류됨.

9.1 해결책 2가지 축 (Port Type vs Boolean)

  • semanage port ... -t http_port_thttpd_t가 “특정 포트”로 connect 가능하도록 포트 타입을 분류함 → 허용 범위가 좁고, 최소 권한 원칙에 가까움

  • setsebool -P httpd_can_network_connect 1httpd_t의 “네트워크 connect 자체”를 허용하는 Boolean → 허용 범위가 넓고, 서버 성격에 따라 더 실용적일 수 있음

즉, httpd_can_network_connect는 완전히 다른 문제가 아니라
“proxy_pass + SELinux” 흐름과 동일 카테고리(SELinux 내부 정책 허용) 에 속하며,
단지 허용 방식이 다른 것임.

9.2 언제 어떤 방식을 선택하는가 (운영 기준)

A) semanage port 방식 (포트 타입 분류) — 기본 권장

정해진 포트(예: 3000)로만 proxy_pass가 필요한 구조에서 적합함.

  • Next.js가 127.0.0.1:3000에서만 listen
  • firewall에서 3000 포트는 외부 미개방
  • Nginx가 동일 서버에서 proxy_pass http://127.0.0.1:3000 수행

이 경우:

추가

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

수정

sudo semanage port -m -t http_port_t -p tcp 3000

B) httpd_can_network_connect 방식 (Boolean) — 조건부 허용

서버가 Reverse Proxy / Gateway 성격이 강하고, Nginx가 다양한 내부 포트/백엔드로 connect 해야 하는 구조에서는 boolean 방식이 운영상 더 단순할 수 있음.

sudo setsebool -P httpd_can_network_connect 1
sudo systemctl restart nginx

9.3 반드시 기억할 점 (오해 금지)

  • semanage port방화벽 개방이 아니라 “포트 타입 분류”
  • setsebool방화벽 개방이 아니라 “프로세스 권한 허용”
  • 외부 노출 여부는 firewalld(방화벽) 가 결정함

firewall = “들어오게 할지”
SELinux = “누가 쓰게 할지”


10. 최종 결론

  • semanage port보안 완화가 아니라 보안 유지 수단
  • Nginx + Next.js + SELinux Enforcing은 완전히 공존 가능
  • 이해 없이 설정만 하면 반드시 사고 남

이 문서를 이해했다면
더 이상 proxy_pass + SELinux로 삽질할 일은 없다