LabHub
学习 学习路径 课程

FDE综合实战:仓库收到了三次相同订单

开启代理之后,内部 API 挂了

在 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)은 그대로 두고 프록시 값만 로컬 센티널 주소로 바꿔 끼우면, 센티널이 연결을 받았는지로 판정할 수 있습니다. 채점기는 무작위 도메인과 프록시 주소로 시험합니다.