9. 사내 프록시 — 프로그램마다 따로 논다
사내 프록시가 어려운 이유는 하나다 — “시스템 프록시 설정”이라는 것이 리눅스에 없다. 프로그램마다 자기 방식으로 따로 읽는다
이 장에서 처음 나오는 말5개
포워드 프록시forward proxy- 내부에서 외부로 나가는 요청을 대신 보내주는 중계 서버. 사내망에서 인터넷 접근을 한 지점으로 모아 통제·기록하려고 둔다. 이 장의 "프록시"는 전부 이것이다.
CONNECT 터널- HTTPS 요청을 프록시로 보낼 때 쓰는 방식. 프록시에 "이 호스트의 443으로 터널을 열어 달라"고 먼저 요청한 뒤 그 위로 TLS를 한다.
MITM 검사Man-In-The-Middle inspection- 프록시가 TLS를 일단 풀어서 내용을 검사하고 자기 인증서로 다시 암호화하는 것. 사내 보안 정책으로 흔하다 — 그래서 클라이언트에 사내 CA 인증서를 심어야 한다.
CACertificate Authority- 인증서에 서명해 주는 기관. 브라우저·OS는 신뢰하는 CA 목록을 들고 있고, 그 목록에 없는 CA가 서명한 인증서는 거부된다. 사내 CA는 목록에 없으므로 직접 추가해야 한다.
NO_PROXY- "이 주소들은 프록시를 거치지 말라"는 예외 목록. 빠뜨리면 사내 서버끼리의 통신까지 프록시로 나갔다가 막힌다 — 프록시 설정에서 가장 사고가 잦은 항목이다.
왜 한 곳에 설정할 수 없는가
섹션 제목: “왜 한 곳에 설정할 수 없는가”환경변수를 읽는 프로그램이 가장 많지만 전부는 아니다. apt·snap·systemd 서비스·git·docker는 각자 자기 설정을 본다 — “curl은 되는데 apt는 안 돼요”의 정체가 이것이다.
1. 환경변수 — 기본 축
섹션 제목: “1. 환경변수 — 기본 축”# 확인부터env | grep -i proxyecho $http_proxy $https_proxy $no_proxy/etc/environment (모든 사용자·모든 세션에 적용, 로그인 시 읽힌다)
http_proxy="http://proxy.corp.local:3128"https_proxy="http://proxy.corp.local:3128"no_proxy="localhost,127.0.0.1,::1,.corp.local,10.0.0.0/8,169.254.169.254"HTTP_PROXY="http://proxy.corp.local:3128"HTTPS_PROXY="http://proxy.corp.local:3128"NO_PROXY="localhost,127.0.0.1,::1,.corp.local,10.0.0.0/8,169.254.169.254"no_proxy — 가장 사고가 잦은 줄
섹션 제목: “no_proxy — 가장 사고가 잦은 줄”| 넣어야 하는 것 | 이유 |
|---|---|
localhost,127.0.0.1,::1 | 자기 자신에게 가는 요청까지 프록시로 나가면 전부 실패한다 |
.corp.local (앞의 점) | 사내 도메인 전체. 점 하나가 서브도메인 매칭을 만든다 |
10.0.0.0/8 등 사내 대역 | 사내 IP 직접 접근 |
169.254.169.254 | 클라우드 메타데이터 주소. 빠뜨리면 인스턴스가 이상해진다 |
2. 프로그램별 설정
섹션 제목: “2. 프로그램별 설정”apt는 환경변수를 보지 않는다. 별도 파일이 필요하다.
/etc/apt/apt.conf.d/95proxy
Acquire::http::Proxy "http://proxy.corp.local:3128";Acquire::https::Proxy "http://proxy.corp.local:3128";// 사내 미러는 직접Acquire::http::Proxy::mirror.corp.local "DIRECT";sudo apt update -o Debug::Acquire::http=true # 실제로 프록시를 타는지 확인apt-config dump | grep -i proxy인증이 필요하면 http://사용자:비밀번호@proxy… 형식인데, 파일에 평문으로 남는다 —
sudo chmod 600 하고, 가능하면 IP 기반 인증을 요청한다.
snap도 자기 설정을 따로 쓴다.
sudo snap set system proxy.http="http://proxy.corp.local:3128"sudo snap set system proxy.https="http://proxy.corp.local:3128"snap get system proxy그래도 안 되면 snapd 데몬 자체에 환경변수를 준다 —
sudo systemctl edit snapd 로 아래의 systemd 방식을 적용하고 systemctl restart snapd.
부팅 시 뜨는 데몬은 로그인 셸을 거치지 않으므로 /etc/environment의 값을 못 받는 경우가 많다.
유닛에 직접 준다(5장).
sudo systemctl edit myapp[Service]Environment="HTTP_PROXY=http://proxy.corp.local:3128"Environment="HTTPS_PROXY=http://proxy.corp.local:3128"Environment="NO_PROXY=localhost,127.0.0.1,.corp.local,10.0.0.0/8"sudo systemctl daemon-reload && sudo systemctl restart myappsudo tr '\0' '\n' < /proc/$(systemctl show -p MainPID --value myapp)/environ | grep -i proxy마지막 줄이 실제로 먹었는지 확인하는 결정적 방법이다(4장).
도커는 두 곳이 완전히 별개라서 가장 헷갈린다.
# (1) 데몬 — 이미지 pull 이 여기를 쓴다sudo systemctl edit docker[Service]Environment="HTTP_PROXY=http://proxy.corp.local:3128"Environment="HTTPS_PROXY=http://proxy.corp.local:3128"Environment="NO_PROXY=localhost,127.0.0.1,.corp.local,registry.corp.local"sudo systemctl daemon-reload && sudo systemctl restart dockersudo docker info | grep -i proxy// (2) 클라이언트 — 빌드와 컨테이너 실행이 여기를 쓴다{ "proxies": { "default": { "httpProxy": "http://proxy.corp.local:3128", "httpsProxy": "http://proxy.corp.local:3128", "noProxy": "localhost,127.0.0.1,.corp.local" } }}pull은 되는데 build 안의 apt-get이 안 되면 (2)를 안 한 것이다.
# git — HTTPS 원격git config --global http.proxy http://proxy.corp.local:3128git config --global https.proxy http://proxy.corp.local:3128git config --global --unset http.proxy # 해제
# git — SSH 원격(git@…)은 프록시 설정을 안 본다. ~/.ssh/config 로# Host github.com# ProxyCommand nc -X connect -x proxy.corp.local:3128 %h %p
# pip — /etc/pip.conf 또는 ~/.pip/pip.conf# [global]# proxy = http://proxy.corp.local:3128
# npm — ~/.npmrcnpm config set proxy http://proxy.corp.local:3128npm config set https-proxy http://proxy.corp.local:3128요약표
섹션 제목: “요약표”| 프로그램 | 설정 위치 | 환경변수를 보나 |
|---|---|---|
curl · wget | 환경변수 (curl은 -x도) | ✅ (curl은 소문자만) |
apt | /etc/apt/apt.conf.d/95proxy | ❌ |
snap | snap set system proxy.* | ❌ |
| systemd 서비스 | 유닛 drop-in Environment= | ❌ (로그인 셸을 안 거친다) |
docker pull | 데몬 drop-in | ❌ |
docker build/run | ~/.docker/config.json | ❌ |
git (https) | git config http.proxy | ⚠️ 보긴 하지만 config가 우선 |
git (ssh) | ~/.ssh/config의 ProxyCommand | ❌ |
pip · npm | 환경변수 또는 각자 config | ✅ |
3. 사내 사설 CA 인증서 — TLS가 깨질 때
섹션 제목: “3. 사내 사설 CA 인증서 — TLS가 깨질 때”프록시가 MITM 검사를 하면 서버 인증서가 사내 CA가 서명한 것으로 바뀐다. OS는 그 CA를 모르니 전부 거부한다.
curl: (60) SSL certificate problem: self-signed certificate in certificate chainSSL: CERTIFICATE_VERIFY_FAILED (Python)unable to get local issuer certificate (git · node)x509: certificate signed by unknown authority (docker · go)이 메시지들이 보이면 전부 같은 원인이고 해법도 같다.
-
사내 CA 인증서(
.crt, PEM 형식)를 받는다. 없으면 실제 연결에서 뽑는다터미널 창 openssl s_client -showcerts -connect example.com:443 -servername example.com </dev/null \| openssl x509 -outform PEM > /tmp/corp-ca.crtopenssl x509 -in /tmp/corp-ca.crt -noout -subject -issuer -dates -
확장자가 반드시
.crt여야 하고 PEM 형식이어야 한다 (.pem은 무시된다)터미널 창 sudo cp /tmp/corp-ca.crt /usr/local/share/ca-certificates/corp-ca.crtsudo update-ca-certificates# 1 added, 0 removed; done. -
확인
터미널 창 curl -vI https://example.com # 이제 --insecure 없이 통과해야 한다
진단 — 프록시를 타고 있는지 어떻게 아나
섹션 제목: “진단 — 프록시를 타고 있는지 어떻게 아나”curl -v https://example.com 2>&1 | head -20# 프록시 경유: * Connected to proxy.corp.local (10.x.x.x) port 3128# > CONNECT example.com:443 HTTP/1.1# 직접 연결: * Connected to example.com (93.x.x.x) port 443
curl -v -x http://proxy.corp.local:3128 https://example.com # 환경변수 무시하고 강제curl -v --noproxy '*' https://example.com # 프록시 강제 우회 — 둘을 비교한다| 증상 | 원인 |
|---|---|
407 Proxy Authentication Required | 프록시 인증 필요 — 자격 증명 또는 IP 등록 |
Connected to proxy … 후 타임아웃 | 프록시는 닿는데 그 목적지를 프록시가 막고 있다 (차단 정책) |
| 프록시 주소로 연결 자체가 실패 | 프록시 주소/포트 오타, 또는 프록시까지의 경로 문제(8장) |
내부 서버인데 Connected to proxy | no_proxy에 그 주소가 빠졌다 |
사용자로는 되고 sudo로는 실패 | sudo가 환경변수를 버렸다 — sudo -E |
| CLI는 되는데 서비스는 실패 | 데몬에 환경변수가 안 갔다 — /proc/PID/environ 확인 |
9장 요약
섹션 제목: “9장 요약”- 리눅스에는 통합 프록시 설정이 없다 — 환경변수 · apt · snap · systemd · docker · git이 전부 따로다
- 환경변수는 대소문자 둘 다,
https_proxy값도 보통http://로 시작한다 sudo는 프록시 환경변수를 버린다 —sudo -E또는env_keepno_proxy에localhost· 사내 도메인 · 메타데이터 IP를 빠뜨리면 사고가 난다- 데몬이 프록시를 먹었는지는
/proc/PID/environ으로 확정한다 - TLS 오류 4종은 전부 같은 원인 —
/usr/local/share/ca-certificates/*.crt+update-ca-certificates. 단 Node·Python·Java는 별도 지정이 필요하다 -k·sslVerify false는 진단용이지 해결이 아니다