# pmproxy 마케팅용 IP 제한 우회 프록시 — 폰을 출구로. 포털들이 통신사 무선 대역을 차단 못 한다는 점을 IP 풀로 활용한다. ## 아이디어 요약 - 포털·서비스의 IP당 제한(회원가입·투표·폼 제출 등)을 우회할 출구 IP가 필요 - 통신사 무선 IP 대역은 **통째로 차단 불가** (실제 모바일 사용자가 같이 걸림) → 사실상 "차단 불가 IP" - 폰은 네트워크 재연결(비행기모드 토글 등)만 하면 통신사가 새 IP를 배정 → **자연 로테이션** - 모바일 앱(에이전트)이 폰을 프록시 출구로 만들고, 이를 여러 대 확보해 마케팅 자동화 트래픽을 분산 ## 결정 기록 (261002) | 항목 | 결정 | 비고 | |---|---|---| | 운영 모델 | **A안 — 직접 관리 폰 풀** | 내 폰 + 지인 1대(안드로이드). Honeygain식 참여 풀(B안)은 보류 — IP 다양성은 좋으나 보상·신뢰·앱 심사 비용 큼. A로 검증 후 확장 | | 터널 프로토콜 | **WS(WebSocket)** 전환 | 기존 autossh 역방향 터널은 검증됐지만 지인 폰에 Termux 셋업이 필요. WS 에이전트로 앱/스크립트 셋업 간소화 | | 중계 모드 | **L4 바이패스 (비-MITM)** | haproxy식 스트림 릴레이. 어디서도 TLS 종단·복호화 안 함. CA 설치 불필요, 요청 변조 없음 | | 현황 | **v1 구현·검증 완료 (261002)** | 폰 1대(본인, SKT) 동작 중 + 지인 1명 대기 | ## 통신 모델 — L4 바이패스 - 클라이언트(gs2의 작업 러너)는 브로커 SOCKS5 인터페이스로 붙음 (`curl -x socks5h://127.0.0.1:1080 https://target ...`) - 브로커는 요청을 (폰 선택 + DIAL host:port)로 번역해 WS 터널로 전달 — **본문을 볼 이유가 없음** - 폰 에이전트는 DIAL 프레임을 받아 **폰 네트워크에서 직접 TCP 다이얼** 후 양방향 raw 바이트 릴레이 — 폰에 로컬 프록시(tinyproxy) 불필요 - TLS 종단은 클라이언트↔대상 사이트 그대로 → TLS 핑거프린트(실 클라이언트 것) 유지, 폰은 암호문만 경유 → 참여자 신뢰 부담 최소 - 고정 타깃 단순 릴레이(haproxy 백엔드식)도 옵션: DIAL 없이 정책 고정 ## 아키텍처 ``` [마케팅 작업 클라이언트] (gs2에서 동작) │ SOCKS5 ▼ [gs2 프록시 브로커] — 에이전트 레지스트리(세션·출구 IP·헬스), 배분 정책 │ (폰→gs2 outgoing wss 연결 위로 DIAL+바이트 릴레이) ▼ ┌──────── 폰 풀 ────────┐ │ 폰1 (본인, SKT) │ │ 폰2 (지인, 안드로이드) │ ← 재연결 시 출구 IP 자동 로테 └──────────────────────┘ ``` - 폰은 NAT 안이므로 **폰→브로커 outgoing 연결**만 사용 (브로커가 폰 IP를 전혀 몰라도 됨) - 폰 에이전트: wss 연결 유지(백오프 재접속) + DIAL 다이얼러 - 브로커: 요청별 폰 배분(sticky/round-robin), 폰별 현재 출구 IP 추적·기록 - IP 로테이션은 폰 특성(재연결)에 맡기고, 브로커는 에이전트 재접속을 감지해 새 IP로 갱신. 스테일 감지·엔드투엔드 헬스체크 레시피는 autossh 운영 경험 승계 ## 보안·전제 - 에이전트별 발급 토큰 인증, **wss(TLS)** 사용 - 브로커·에이전트 어디서도 인증서 교체·트래픽 복호화 없음 (non-MITM 보장) - 폰에 인바운드 포트 없음 - 지인 폰: 참여 동의 전제, 폰은 암호문 바이트만 중계 ## 관련 - [[아이디어노트old/scraping/증권사API-프록시]] — COM→REST 프록시 (별개 아이디어, 프록시 계열 선례) - [[💰/조사노트/260928-세션정리]] — 폰 역프록시(tinyproxy→autossh) 최초 구축 기록 - [[💰/조사노트/261001-7단지-매물전수]] — 역프록시+CDP 활용 실전 기록 (헤더 완전복제는 CDP 쪽, 본 프록시는 트랜스포트만) - 코드: 로컬 `~/pmproxy` (설계 초기), 운영 노하우는 로컬 스킬 proxy-phone-gs2 ## 구현 기록 (v1 — 261002) - 배포: gs2 `~/work/pmproxy` (PM2 `pmproxy`) — SOCKS5 `127.0.0.1:1080`, WS `:8300`, Caddy `pmproxy.app.gslump.com`로 wss 개방 - 에이전트: 내 폰 Termux `run-agent.sh` — wss 재접속(백오프) + DIAL 다이얼러 + egress IP META 보고 - 검증: gs2에서 `curl -x socks5h://127.0.0.1:1080 https://api.ipify.org` → `106.101.209.37` (SKT) 반환, HTTPS 성공. TLS 종단 미개입 확인 - **3차 검증: 안드로이드 서비스 앱으로 완전 교체 (261002)** — `~/pmproxy/android/`(Kotlin, OkHttp+coroutines, FGS specialUse — targetSdk 35 dataSync 6h 제한 회피, 프로그래밍 방식 최소 UI, 크래시 로그 핸들러). **온디바이스 빌드**: qemu-user-x86_64 + x86_64 glibc sysroot로 x86 SDK 빌드체인 기동 (로컬 검증 셋업 gist에 기록済). phone1 터널 권한이 Termux 스크립트 → 앱으로 이관 - 폰에 tinyproxy 불필요 — 에이전트가 직접 다이얼. **구버전(폰 tinyproxy 8888 + autossh 18088)은 동일일(261002) 폐기** — 프로세스 kill, 부활 절차는 폐기 스킬에 보존 - 코드: 로컬 `~/pmproxy` — 비밀은 전부 `.env`(600), 리포·채팅엔 raw 노출 없음 ## 빌드툴체인 (ARM 네이티브 — 261003) - aapt2 = `~/android-tools/aapt2` (rendiix/termux-aapt arm64 프리뷰트 2.19) + zipalign = termux `aapt` pkg - 등록: **프로젝트** `android/gradle.properties`의 `aapt2=` (절대경로 필수 — `$HOME` 확장 안 됨) - 클린 빌드 11초 통과 — 온디바이스 빌드 플로우 완결