LabHub
배우기 러닝패스 코스

FDE Capstone: The Warehouse Got the Same Order Three Times

We turned on the proxy and the internal API died

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

고객 사내 프록시 설정에서 curl·Python urllib·requests 가 각각 어느 길로 가는지 기록하는 가짜 프록시로 직접 재고, 세 도구가 모두 같은 길로 가는 설정·연동기·판정 도구를 만든다.

왜 중요한가

프록시 환경 변수는 표준이 아니라 관습이라 도구마다 해석이 다르다. 그래서 고객 설정을 넣은 뒤 curl 헬스체크는 초록불인데 파이썬 수집기만 사내 API 에서 403 을 받는 일이 생긴다. 추론으로 설정을 고치면 한 도구를 살리고 다른 도구를 죽이기 쉽다. 이 실습은 "그 요청이 프록시에 도착했는가" 를 기록으로 확인하는 습관을 만든다.

재료: /opt/lab/p1a-proxy/ — corpnet.py(가짜 프록시·사내 API), customer.env(고객 설정), cases.tsv(사례 18개), connector.py(문제 있는 연동기). 인터넷은 없다. 127.0.0.2·127.0.0.3 도 이 파드 자신(루프백)이고, corp.example·saascorp.example 같은 이름은 풀리지 않는다 — 직접 가려던 요청은 이름 풀이에서 실패하지만, 프록시 기록에 없다는 것 자체가 "직접 갔다" 는 증거다.

예상 60분. 세션이 끝나면 /root/proxy 는 사라지니 필요한 파일은 따로 보관한다.

단계

  1. python3 /opt/lab/p1a-proxy/corpnet.py up 으로 사내망 흉내를 띄우고, customer.env 를 적용한 상태에서 http://127.0.0.2:8080/health 를 curl·urllib·requests 로 한 번씩 요청한다. 응답 본문의 served_by 와 id 를 보고 /root/proxy/repro.tsv도구<TAB>PROXY|DIRECT<TAB>id 세 줄을 적는다.
  2. cases.tsv 의 02 단계 사례(c01..c05, 대소문자·스킴별 변수)를 세 도구로 실행해 /root/proxy/matrix.tsvcase<TAB>curl<TAB>urllib<TAB>requests 로 적는다.
  3. 03 단계 사례(c06..c10, 접미사·선행 점·별표 붙은 도메인)를 재서 matrix.tsv 에 더한다.
  4. 04 단계 사례(c11..c14, IP·CIDR·포트)를 재서 matrix.tsv 에 더한다.
  5. 05 단계 사례(c15..c18, 별표 한 글자와 소문자·대문자 우선순위)를 재서 matrix.tsv 에 더한다.
  6. 세 도구가 모두 사내 네 곳(127.0.0.2:8080, 127.0.0.3:8080, localhost:8081, api.corp.example:8080)은 직접, 바깥 세 곳(http·https 의 saascorp.example, updates.vendor.example)은 프록시 http://127.0.0.1:3128 로 가게 하는 /root/proxy/fixed.env 를 만든다.
  7. connector.py 를 /root/proxy/connector.py 로 복사해 고친다. CONNECTOR_PROXY 를 계속 쓰되 NO_PROXY 에 걸리는 URL 은 직접 가고, 환경의 HTTP_PROXY·HTTPS_PROXY 는 쓰지 않아야 한다.
  8. /root/proxy/route_probe.py 를 만든다. python3 route_probe.py <env파일> URL... 이 설정 파일의 프록시 주소를 로컬 센티널로 바꿔 끼우고 세 도구를 실제로 실행해, URL 마다 url<TAB>curl<TAB>urllib<TAB>requests 를 출력하고 판정이 갈리면 종료 코드 3, 모두 같으면 0 으로 끝나야 한다.

참고

고객 설정으로 장애 재현하고 증거 남기기

corpnet 을 띄우고 customer.env 로 세 도구의 요청을 한 번씩 보낸 뒤 /root/proxy/repro.tsv 에 도구·길·id 를 적는다.

응답 본문의 served_by 가 corp-proxy 면 프록시를 탄 것입니다. id 는 logs 의 기록 줄과 짝이 맞아야 하고, 기록의 User-Agent 로 어느 도구가 보냈는지 교차 확인됩니다. customer.env 는 set -a 로 하위 셸에서만 export 하세요.

대문자 HTTP_PROXY 와 ALL_PROXY 재기

cases.tsv 의 c01..c05 를 세 도구로 실행해 /root/proxy/matrix.tsv 에 PROXY/DIRECT 로 적는다.

사례마다 env -i 로 깨끗한 환경을 만들고, 요청 전후로 proxy.jsonl 의 줄 수가 늘었는지 보세요. curl 매뉴얼의 ENVIRONMENT 절에서 http_proxy 에만 붙은 예외를 찾아보세요.

접미사·선행 점·별표 붙은 도메인

c06..c10 을 재서 /root/proxy/matrix.tsv 에 더한다(앞 사례 줄은 지우지 않는다).

직접 가려던 요청은 이름 풀이에서 실패합니다. 실패 여부가 아니라 프록시 기록에 도착했는지로 판정하세요. saascorp.example 은 corp.example 로 끝나는 다른 회사 이름입니다.

CIDR 과 포트를 적은 NO_PROXY

c11..c14 를 재서 /root/proxy/matrix.tsv 에 더한다.

CIDR 지원은 curl 매뉴얼의 --noproxy 설명에 버전과 함께 나옵니다. urllib 문서는 no_proxy 항목에 포트를 붙일 수 있다고 적습니다. 문서가 말하지 않는 도구는 재 봐야 압니다.

별표 한 글자와 소문자 우선

c15..c18 을 재서 /root/proxy/matrix.tsv 에 더한다.

별표가 목록 안의 한 항목일 때와 목록 전체일 때를 비교하세요. 빈 문자열인 소문자 변수가 '설정 안 됨' 으로 읽히는지 '빈 목록' 으로 읽히는지도 도구마다 다릅니다.

세 도구의 공통분모로 설정 다시 쓰기

사내 네 곳은 직접, 바깥 세 곳은 http://127.0.0.1:3128 로 가게 하는 /root/proxy/fixed.env 를 만든다.

앞에서 채운 표에서 세 도구가 모두 같은 답을 낸 표기만 고르세요. 대소문자, 도메인 앞의 점, CIDR 대신 쓸 것, 포트를 붙일지 여부 네 가지를 결정해야 합니다.

proxies 인자를 쓰는 연동기 고치기

/opt/lab/p1a-proxy/connector.py 를 /root/proxy/connector.py 로 복사해 NO_PROXY 를 지키도록 고친다.

requests.utils 에 URL 과 no_proxy 문자열로 우회 여부를 알려 주는 함수가 있습니다. 세션의 trust_env 는 환경 변수 프록시를 쓸지 정합니다. 사내 IP 를 코드에 박으면 다른 NO_PROXY 로 채점할 때 떨어집니다.

어떤 설정이든 도구별 길을 재는 탐침

/root/proxy/route_probe.py 를 만든다. env 파일과 URL 들을 받아 세 도구의 길을 실제 실행으로 판정해 TSV 로 출력하고, 갈리면 3·같으면 0 으로 끝난다.

고객 프록시 주소는 이 파드에서 닿지 않습니다. 판단 규칙(no_proxy)은 그대로 두고 프록시 값만 로컬 센티널 주소로 바꿔 끼우면, 센티널이 연결을 받았는지로 판정할 수 있습니다. 채점기는 무작위 도메인과 프록시 주소로 시험합니다.