infra
Platform

모듈 맵

[Network] 인터넷이 차단된 서버를 외부와 연결하는 Proxy 구성 실무

0 / 35 완료

펼치기
0 / 35 완료0%

Networking · 29 / 35

[Network] 인터넷이 차단된 서버를 외부와 연결하는 Proxy 구성 실무

Squid Proxy로 폐쇄망 서버의 패키지 업데이트 통로를 구성합니다

🚨INCIDENT ALERT
HIGH

폐쇄망 서버에서 보안 패치가 실패했다는 알림이 왔습니다. 인터넷이 막힌 환경이라 yum update도, 외부 패키지 저장소 접근도 모두 타임아웃됩니다.

네트워크를 무작정 열 수는 없고, 감사 로그가 남는 제한된 통로만 허용해야 합니다. 이때 프록시 서버 설계가 운영과 보안을 동시에 살립니다.

폐쇄망 환경과 프록시 서버 구성

금융, 국방, 의료, 공공기관 시스템을 운영하다 보면 반드시 마주치는 환경이 있습니다. 바로 폐쇄망입니다. 인터넷이 완전히 차단된 서버에서 어떻게 OS 패키지를 업데이트하고, 의존성 라이브러리를 설치할까요? 이 챕터에서는 DMZ 존에 배치된 Squid Proxy를 통해 폐쇄망 서버가 안전하게 외부 패키지 저장소에 접근하는 방법을 배웁니다.


폐쇄망 아키텍처 이해

이번 챕터에서 배울 것
  • 1폐쇄망(Air-Gap Network) 개념 및 물리적·논리적 망 분리 수준 비교
  • 23단계 망 분리 아키텍처 — 인터넷 / DMZ / 내부망 구성
  • 3DMZ와 Bastion Host의 역할 및 보안 강화 설정
  • 4Squid Proxy ACL 화이트리스트로 허용 도메인 제한
  • 5폐쇄망 서버에서 apt, pip, yum/dnf 프록시 설정 방법
실습 환경 준비
Squid Proxy 설치 (Ubuntu/Debian)
sudo apt-get install squid -y
Squid 설정 문법 검사
sudo squid -k parse
캐시 디렉토리 초기화 후 서비스 재시작
sudo squid -z && sudo systemctl restart squid
apt 프록시 설정 파일 생성 위치

/etc/apt/apt.conf.d/01proxy — Acquire::http::Proxy 항목 추가

💡개념

망 분리 아키텍처 — 물리적/논리적 분리와 DMZ

금융권 프로젝트에 투입됐더니 개발 서버에서 apt update가 아예 안 됩니다. 인터넷 연결이 차단된 폐쇄망 환경이기 때문입니다. 패키지 하나 설치하려 해도 프록시 서버를 거쳐야 하고, 어떤 서버는 특정 포트만 열려있습니다. 망 분리 아키텍처의 구조를 이해하지 못하면 이 환경에서 기본 작업조차 막혀서 손도 못 댑니다.

망 분리 아키텍처 — 물리적/논리적 분리와 DMZ

망 분리의 필요성

보안이 중요한 시스템은 인터넷과의 연결을 차단하여 외부 공격 표면을 최소화합니다.

망 분리 수준:

1. 논리적 분리 (소프트웨어 기반)
   - VLAN, 방화벽, ACL로 트래픽 제어
   - 물리 인프라 공유, 설정 오류 시 데이터 유출 가능
   - 구현 비용 낮음

2. 물리적 분리 (Air-Gap)
   - 완전히 다른 물리 네트워크 장비 사용
   - 케이블 자체가 연결되지 않음
   - 최고 수준 보안 (군사, 원자력, 금융 핵심 시스템)

3단계 망 분리 아키텍처

실제 엔터프라이즈 환경에서 흔히 볼 수 있는 구성입니다.

┌─────────────────────────────────────────────────────────────────┐
│                     인터넷 (외부망)                              │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                    ┌──────▼──────┐
                    │  외부 방화벽 │
                    └──────┬──────┘
                           │
┌──────────────────────────▼──────────────────────────────────────┐
│                      DMZ (비무장 지대)                           │
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │ Bastion Host │  │ Squid Proxy  │  │  웹 서버 등  │          │
│  │ (SSH 게이트웨이) │ (패키지 통로) │  │ (공개 서비스) │         │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                    ┌──────▼──────┐
                    │  내부 방화벽 │
                    └──────┬──────┘
                           │
┌──────────────────────────▼──────────────────────────────────────┐
│                      내부망 (폐쇄망)                             │
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │   WAS 서버   │  │   DB 서버    │  │  배치 서버   │          │
│  │ (인터넷 차단) │  │ (인터넷 차단) │  │ (인터넷 차단) │         │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
└─────────────────────────────────────────────────────────────────┘

DMZ (비무장 지대)

DMZ(DeMilitarized Zone)는 외부 인터넷과 내부 폐쇄망 사이에 위치한 중간 지대입니다.

DMZ의 역할:

  • 외부에서 접근 가능한 서비스 호스팅 (웹, 메일, DNS)
  • 내부망과 외부망 사이의 완충 역할
  • Squid Proxy를 통한 제한적 인터넷 접근 통로 제공

DMZ 보안 원칙:

외부 방화벽: 인터넷 → DMZ 허용 (필요한 포트만)
내부 방화벽: DMZ → 내부망 차단 (원칙), 특정 트래픽만 허용

Bastion Host

Bastion Host(요새 호스트)는 외부에서 내부망으로의 유일한 SSH 진입점입니다.

외부 엔지니어
    │ SSH (22번)
    ▼
Bastion Host (DMZ)
    │ SSH (내부 서버들)
    ▼
내부 서버 (폐쇄망)

특징:
- 모든 접근 로그 기록
- MFA 필수 적용
- 최소한의 소프트웨어만 설치
- 강화 OS 설정 (CIS Benchmark)
💡개념

Squid Proxy — 폐쇄망의 패키지 업데이트 통로

Squid Proxy가 필요한 이유

폐쇄망 서버는 인터넷 직접 연결이 불가능하지만, OS 보안 패치와 패키지 업데이트는 꾸준히 해야 합니다. Squid Proxy는 DMZ에서 제한된 도메인으로만 트래픽을 중계합니다.

폐쇄망 서버
    │ http://dmz-proxy:3128 경유
    ▼
Squid Proxy (DMZ)
    │ ACL 검사 (허용된 도메인만 통과)
    ├── archive.ubuntu.com → 허용
    ├── pypi.org → 허용
    ├── registry.npmjs.org → 허용
    ├── www.google.com → 차단 (403 Forbidden)
    └── 기타 도메인 → 차단
    │
    ▼
인터넷

Squid Proxy 동작 원리

HTTP 프록시 흐름:

클라이언트 → GET http://archive.ubuntu.com/ubuntu/... HTTP/1.1
             Host: archive.ubuntu.com
             [Proxy 요청 형식: 전체 URL 포함]

Squid → ACL 검사 → 허용됨
Squid → archive.ubuntu.com에 직접 요청
Squid → 응답 캐시 저장 (선택)
Squid → 클라이언트에 응답 전달

Squid 주요 설정 지시어:

지시어역할예시
http_port리스닝 포트http_port 3128
acl접근 제어 목록 정의acl allowed_sites dstdomain .ubuntu.com
http_accessACL 허용/차단http_access allow allowed_sites
cache_dir캐시 저장 위치cache_dir ufs /var/spool/squid 10000 16 256

Squid 캐시의 장점

패키지 파일을 캐시하면 같은 파일을 여러 서버가 요청할 때 외부 트래픽을 줄일 수 있습니다.

첫 번째 서버의 요청:
서버A → Squid → 인터넷 (package.deb 다운로드) → Squid 캐시 저장

두 번째 서버의 요청:
서버B → Squid → 캐시 히트! → 인터넷 요청 없이 즉시 응답

1Squid Proxy 동작 확인 — 프록시 경유 vs 직접 연결 비교

폐쇄망 환경에서 프록시 설정이 제대로 동작하는지 단계별로 검증합니다.

로컬 또는 서버
# 1단계: 직접 연결 차단 확인 (폐쇄망 서버에서)
curl -v --connect-timeout 5 https://pypi.org/
# curl: (28) Connection timed out after 5000 milliseconds
# → 직접 연결 불가 확인

# 2단계: 프록시 경유 연결 시도
curl -v https://pypi.org/ --proxy http://dmz-proxy:3128
# * Connected to dmz-proxy (10.0.1.10) port 3128
# * CONNECT pypi.org:443 HTTP/1.1
# * Proxy replied 200 to CONNECT request
# → 프록시 경유 성공

# 3단계: 환경 변수로 프록시 설정 후 apt 동작 확인
export http_proxy="http://dmz-proxy:3128"
export https_proxy="http://dmz-proxy:3128"
apt-get update -y

# 4단계: Squid 로그에서 요청 흔적 확인 (프록시 서버에서)
sudo tail -20 /var/log/squid/access.log
# 1711504800.123  125 10.0.0.20 TCP_MISS/200 12345 GET http://archive.ubuntu.com/...
curl -v https://pypi.org/ --proxy http://localhost:3128
🔍실행 후 확인할 것
  • curl --proxy 로 pypi.org에 접근할 때 CONNECT 메서드가 사용되는지 확인 (HTTPS 터널링)
  • Squid access.log에서 TCP_MISS(최초 요청)와 TCP_HIT(캐시 재사용) 차이 확인
  • 같은 패키지 파일을 두 번 요청했을 때 두 번째 요청이 더 빠른지 (Squid 캐시 효과)
  • http_proxy 설정 없이 curl 하면 타임아웃이 나는지 확인 (폐쇄망 격리 검증)
  • squid -k parse 명령이 에러 없이 통과하는지 확인 (설정 문법 오류 없음)

트러블슈팅

폐쇄망 프록시 환경에서의 인증 및 캐시 만료 장애 극복

보안 통제를 위해 폐쇄망에서 Squid 프록시를 통해 외부 오픈소스 레포지토리에 연결할 때, 다운로드 타임아웃이나 인증 실패 장애가 다발합니다.

환경 변수 상속 및 확인: 리눅스 셸 세션에서 curl이나 apt 패키지 매니저가 프록시를 타도록 http_proxyhttps_proxy 환경 변수를 정상 주입했는지 점검합니다.

로컬 터미널
# 실습 디렉토리 준비
mkdir -p /tmp/networking/part6/exam_29 && cd /tmp/networking/part6/exam_29

$ export http_proxy="http://192.168.1.100:3128"

프록시 캐시 풀 강제 Prune: 캐시 오염으로 인해 계속 깨진 바이너리가 받아진다면 Squid 서버 데몬의 캐시 디렉토리를 완전히 비워주거나 재기동하여 캐시 풀을 정화시킵니다.


증상

폐쇄망 서버에서 pip install 실행 시 일부 패키지만 설치되고 의존성 패키지 설치가 실패합니다.

로컬 터미널
pip install pandas
# Collecting pandas
# Downloading pandas-2.0.0.tar.gz ...
# Collecting numpy>=1.21 (from pandas)
# ERROR: Could not find a version that satisfies the requirement numpy
# ERROR: No matching distribution found for numpy

curl로 직접 확인:

로컬 또는 서버
curl -v http://files.pythonhosted.org/packages/numpy-1.24.tar.gz \
    --proxy http://dmz-proxy:3128
# [Response] HTTP/1.1 403 Forbidden
# [Response] X-Squid-Error: ERR_ACCESS_DENIED 0

원인 진단

로컬 터미널
# Squid 프록시 서버에서 access.log 확인
sudo tail -100 /var/log/squid/access.log | grep DENIED

# 출력 예시:
# 1711504800.123  125 10.0.0.20 TCP_DENIED/403 4567 GET
# http://files.pythonhosted.org/... - HIER_NONE/- text/html

# files.pythonhosted.org가 ACL에 없음을 확인
grep pythonhosted /etc/squid/squid.conf
# (아무것도 안 나옴 = ACL 미등록)

해결

위험 명령어

이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.

로컬 터미널
# Squid 설정에 누락된 도메인 추가
sudo vi /etc/squid/squid.conf

# 기존 pypi ACL 라인 찾아서 추가:
# acl pypi_repos dstdomain pypi.org
# acl pypi_repos dstdomain files.pythonhosted.org  ← 이 줄 추가

# 설정 문법 검사
sudo squid -k parse

# 설정 재로드 (무중단)
sudo squid -k reconfigure

# 또는 재시작
sudo systemctl restart squid

체계적인 도메인 파악 방법:

로컬 터미널
# 설치 시도 후 Squid 로그에서 차단된 도메인 수집
sudo tail -f /var/log/squid/access.log | grep DENIED

# 또는 인터넷 연결된 환경에서 먼저 테스트하여 필요한 도메인 파악
# strace나 wireshark로 DNS 쿼리 캡처

예방 — 도메인 파악 사전 작업

로컬 터미널
# 인터넷 연결 환경에서 pip이 접근하는 도메인 파악
pip install pandas --dry-run -v 2>&1 | grep "Downloading\|http"

# curl로 실제 연결 도메인 확인 (DNS 쿼리 포함)
strace -e trace=network pip install pandas 2>&1 | grep connect

증상

HTTP는 잘 되는데 HTTPS 요청이 실패합니다.

로컬 또는 서버
curl http://archive.ubuntu.com/ --proxy http://dmz-proxy:3128
# 200 OK → 성공

curl https://pypi.org/ --proxy http://dmz-proxy:3128
# curl: (56) Received HTTP code 403 from proxy after CONNECT

원인

HTTPS 트래픽은 HTTP CONNECT 터널링 방식으로 프록시를 통과합니다. Squid에서 CONNECT 메서드와 443 포트를 허용해야 합니다.

HTTPS 프록시 흐름:
클라이언트 → CONNECT pypi.org:443 HTTP/1.1  (프록시에게 터널 요청)
Squid → CONNECT ACL 검사
Squid → pypi.org:443 TCP 연결 수립
Squid → "HTTP/1.1 200 Connection established" 응답
클라이언트 ↔ pypi.org (TLS 핸드셰이크, Squid는 투명하게 중계)

해결

로컬 터미널
# /etc/squid/squid.conf 확인 및 수정

# 올바른 CONNECT 설정이 있는지 확인
grep -A5 "CONNECT" /etc/squid/squid.conf

# 필요한 설정:
# acl CONNECT method CONNECT
# acl ssl_ports port 443
# http_access deny CONNECT !ssl_ports  ← 443 외 CONNECT 차단
# http_access allow internal_nets pypi_repos  ← 이후 허용 규칙

# 또한 CONNECT 허용 규칙이 명시적으로 있어야 함
# squid.conf에 추가:
# http_access allow CONNECT internal_nets pypi_repos

sudo squid -k reconfigure

SSL Bump (선택 사항 — 기업 환경에서 HTTPS 검사):

로컬 터미널
# Squid에서 HTTPS 내용을 검사하려면 SSL Bump 설정 필요
# (별도 인증서 설치 및 클라이언트 신뢰 설정 필요)
# 이는 고급 설정으로, 일반적인 패키지 업데이트용에는 불필요

실무 맥락

💼
실무 맥락
현업 패턴

폐쇄망 환경의 현실

금융권, 공공기관, 국방 분야에서는 망 분리가 법적으로 의무화되어 있습니다.

금융권 망 분리 규정:
- 전자금융감독규정: 인터넷망과 업무망 분리 의무
- 개인정보 처리 시스템: 인터넷망 차단 필수

공공기관:
- 국가사이버안전관리규정: 1·2등급 정보는 인터넷망 완전 분리

패키지 배포 대안 전략

Squid Proxy 외에도 폐쇄망에서 패키지를 관리하는 다양한 방법이 있습니다.

로컬 터미널
# 방법 1: 내부 미러 서버 구축
# apt-mirror로 Ubuntu 저장소 전체를 내부 서버에 복제
sudo apt-get install apt-mirror
# /etc/apt/mirror.list 설정 후 apt-mirror 실행 (수백 GB)

# 방법 2: 오프라인 패키지 번들
# 인터넷 환경에서 패키지 다운로드
apt-get download package1 package2 package3
# USB/CD로 폐쇄망 반입 후 설치
sudo dpkg -i *.deb

# 방법 3: Nexus Repository Manager (엔터프라이즈)
# Maven, npm, PyPI, Docker 등 다양한 패키지 타입을 내부 프록시로 관리
# https://www.sonatype.com/nexus-repository-oss

# 방법 4: JFrog Artifactory (클라우드/온프레미스)
# 유사한 기능, 엔터프라이즈 라이선스

Bastion Host 운영 실무

위험 명령어

이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.

로컬 터미널
# Bastion Host 강화 설정 예시

# 1. root 직접 로그인 차단
echo "PermitRootLogin no" >> /etc/ssh/sshd_config

# 2. 비밀번호 인증 비활성화 (키 기반만 허용)
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config

# 3. 모든 SSH 세션 기록 (감사 로그)
# /etc/bashrc 에 추가:
# export HISTTIMEFORMAT="%F %T "
# export PROMPT_COMMAND='history -a'
# readonly HISTFILE

# 4. 접속 허용 IP 제한
echo "AllowUsers engineer@203.0.113.0/24" >> /etc/ssh/sshd_config

# 5. MFA 설정 (Google Authenticator)
sudo apt-get install libpam-google-authenticator
# /etc/pam.d/sshd 에:
# auth required pam_google_authenticator.so

# 6. 세션 타임아웃
echo "ClientAliveInterval 300" >> /etc/ssh/sshd_config
echo "ClientAliveCountMax 2" >> /etc/ssh/sshd_config

sudo systemctl restart sshd

망 분리 환경 구축 시 체크리스트

사전 계획:
□ 허용해야 할 도메인/서비스 목록 작성 (최소화 원칙)
□ 내부 서버의 OS/언어 스택 확인 (apt/yum/pip/npm 등)
□ DMZ 서버 IP 대역 및 방화벽 정책 확정
□ Bastion Host HA 구성 여부 결정

구축 단계:
□ DMZ에 Squid Proxy 설치 및 ACL 설정
□ 내부 방화벽: 폐쇄망 → DMZ 3128 포트만 허용
□ 외부 방화벽: DMZ → 인터넷 80/443 허용
□ 폐쇄망 서버에 프록시 환경 변수 배포

운영 단계:
□ Squid 접근 로그 주기적 검토
□ 허용 도메인 목록 정기 검토 (분기별)
□ 불필요한 도메인 제거
□ 캐시 용량 모니터링
□ 보안 패치 적용 프로세스 문서화

정리

폐쇄망 아키텍처
├── 물리적 분리: 케이블 자체 분리 (최고 보안)
├── 논리적 분리: VLAN, 방화벽 (실용적)
├── DMZ: 외부망-내부망 사이 완충 구역
└── Bastion Host: 유일한 SSH 진입점

Squid Proxy 핵심
├── ACL (acl 지시어): 허용/차단 기준 정의
├── http_access: ACL 기반 허용/거부 규칙 (순서 중요!)
├── 기본 거부: http_access deny all 마지막에 추가
└── 캐시: 자주 요청되는 파일 로컬 저장 (대역폭 절감)

폐쇄망 서버 프록시 설정
├── 환경 변수: export http_proxy=http://dmz-proxy:3128
├── apt: /etc/apt/apt.conf.d/01proxy
├── pip: ~/.config/pip/pip.conf
└── yum/dnf: /etc/yum.conf 또는 /etc/dnf/dnf.conf

트러블슈팅
├── 403 Forbidden → ACL에 도메인 추가 필요
│   └── Squid access.log에서 차단된 도메인 확인
└── HTTPS 실패 → CONNECT 메서드 및 ssl_ports ACL 확인

다음 챕터에서는 DNS 질의 실패와 /etc/resolv.conf 설정을 학습하여, "IP ping은 되는데 도메인 ping이 안 되는" 문제를 즉시 해결하는 방법을 배웁니다.

지식 확인

퀴즈 — 5문제

Q1

폐쇄망(Air-Gap Network)의 정의로 가장 올바른 것은?

Q2

Squid Proxy에서 http_proxy 환경 변수를 설정하는 올바른 방법은?

Q3

Bastion Host의 주요 역할은 무엇입니까?

Q4

Squid Proxy에서 ACL에 등록되지 않은 도메인으로 요청 시 발생하는 응답 코드는?

Q5

apt 패키지 매니저가 Squid Proxy를 경유하도록 설정하는 방법은?

0 / 5 답변

🧪 실습으로 확인하기

포트는 열렸다는데 왜 안 되지? — ss/netstat/telnet으로 TCP 진단

초급

"포트 8080 열었는데요?"와 "왜 안 돼요?" 사이의 간극을 메우는 실습. ss로 바인딩 상태를 확인하고, telnet/nc으로 원격 연결을 테스트하고, iptables 방화벽을 진단하고, 바인딩 주소(0.0.0.0 vs 127.0.0.1)까지 수정하는 4단계 TCP 포트 진단 플로우를 완성한다.

35📋 4단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

networking고급 · 55
[Network] 서브넷, 라우팅 테이블, 인터넷 게이트웨이 설계 가이드
Networking 트랙 계속
docker입문 · 30
[Docker] 백엔드 개발자에게 Docker와 컨테이너 가상화가 필수인 이유
Docker 트랙 시작점