
IPSpinner는 로컬 프록시로 작동하여 요청을 외부 서비스를 통해 리디렉션합니다.
IPSpinner는 들어오는 모든 요청을 사용자가 선택한 다양한 공급자를 통해 리디렉션할 수 있는 로컬 프록시입니다. 목적은 각 요청의 소스 IP 주소를 회전시키는 패스스루(pass-through) 프록시를 만드는 것입니다. 예를 들어, IPSpinner를 통해 무차별 대입(bruteforce) 공격을 실행하면 서버가 수백 개의 서로 다른 IP 주소에서 요청을 받게 되므로 탐지를 피하는 데 도움이 됩니다.
IPSpinner는 현재 AWS(API Gateway), Azure(Cloud Shell) 및 GitHub(GitHub Actions)를 지원합니다.
그림 1: IPSpinner - 전체 구성도
IPSpinner는 외부 서비스를 통해 요청을 리디렉션하는 로컬 프록시로 작동합니다. 이를 위해 IPSpinner는 공급자(provider)와 런처(launcher)를 활용합니다.
공급자는 클라우드 공급자 또는 온라인 서비스 공급자(AWS, Azure, GitHub 등)에 해당하며, 사용자의 요청을 중계하는 데 사용할 수 있는 다양한 서비스, 이른바 런처를 제공합니다(AWS API Gateway, GitHub Actions, Azure Cloud Shell 등).
따라서 IPSpinner를 실행하려면 사용자는 사용하려는 공급자의 자격 증명(credential)과 런처에 대한 추가 구성을 제공해야 합니다. 여러 유형의 런처를 동시에 사용할 수 있으며, IPSpinner는 각 요청에 대해 사용 가능한 런처 중 하나를 무작위로 선택합니다.
또한 IPSpinner는 프리로드(preload) 기능을 구현합니다. 일부 런처는 프록시가 새 호스트를 감지하는 경우 재구성 지연을 피하기 위해 프리로드할 수 있습니다. 이러한 런처의 경우 프리로드 절차가 권장되지만 필수는 아닙니다. 다른 런처의 경우 프리로드가 필요하지 않습니다.
IPSpinner는 요청 전송에 AWS API Gateway를 활용할 수 있습니다. 이 구현은 들어오는 요청을 리디렉션하는 REST API Gateway를 생성하는 FireProx를 기반으로 합니다. 따라서 FireProx는 API Gateway당 여러 호스트를 처리하고 새로운 기능을 구현하도록 조정되었습니다. 요약하면, IPSpinner가 요청을 수신하면 적절한 API Gateway 인스턴스를 선택하거나 생성하여 요청을 전송합니다. 그런 다음 응답을 수집하여 사용자에게 반환합니다. 따라서 대상 서버는 사용자로부터 직접 요청을 받는 것이 아니라 API Gateway로부터 요청을 받게 됩니다. API Gateway는 각 요청에 대해 나가는 IP를 회전시키므로 IPSpinner는 이 기능을 활용하여 IP 주소가 회전되도록 합니다.
그림 2: AWS API Gateway - 전체 구성도
2024년 10월에 작성된 다음 그래프는 전송된 요청 수에 따른 AWS 리전별 사용 가능한 고유 IP 주소 수를 보여줍니다. 대부분의 리전은 100개 이상의 IP 주소를 제공하며, 여러 리전을 동시에 사용할 수 있으므로 사용자는 전 세계 수천 개의 주소를 통해 요청을 프록시할 수 있습니다.
그림 3: AWS API Gateway - 리전별 사용 가능한 IP 주소
마지막으로, 그림 4는 로그 스케일의 녹색 색상 레벨을 사용하여 국가별로 사용 가능한 주소 수를 보여줍니다. 이를 통해 사용자가 어느 대륙의 주소든 사용하여 소스 IP 주소를 위조할 수 있음을 알 수 있습니다.
그림 4: AWS API Gateway - 국가별 IP 주소
IPSpinner는 생성된 FireProx 인스턴스를 정기적으로 삭제하고 갱신하는 회전(rotation) 기능을 구현합니다. 다음 그래프에서 볼 수 있듯이 FireProx 인스턴스를 회전시키면 새로운 IP 하위 집합이 제공될 수 있습니다. 그러나 각 AWS 리전에는 제한된 IP 집합이 있으므로 어느 시점에 이르면 회전해도 새로운 IP가 제공되지 않습니다.
그림 5: AWS API Gateway - 회전 프로세스
이 런처는 프리로딩 절차를 구현합니다. 앞서 말했듯이 필수는 아니지만, 재구성 후 처음 몇 초 동안 발생할 수 있는 재구성 지연이나 동기화 오류를 방지할 수 있습니다.
또한 API Gateway는 기본적으로 X-Forwarded-For 헤더를 설정하며, 이 헤더는 삭제할 수 없지만 덮어쓸 수 있습니다. 따라서 사용자는 IPSpinner 구성에서 각 요청에 대해 무작위 IP가 선택될 IP 주소 범위(IPv4 또는 IPv6 범위)를 지정할 수 있습니다.
IPSpinner는 요청 전송에 Azure Cloud Shell을 활용합니다. Azure Cloud Shell은 Azure 리소스를 관리하기 위한 대화형, 인증된, 브라우저에서 액세스 가능한 터미널입니다. Cloud Shell은 세션별, 사용자별로 제공되는 임시 호스트에서 실행됩니다.
따라서 IPSpinner는 Cloud Shell 세션이 준비된 여러 Azure 사용자를 사용합니다. 그런 다음 각 요청은 초기화된 Cloud Shell로 리디렉션되며, 이후 IP 주소를 재설정하기 위해 갱신됩니다.
그림 6: Azure Cloud Shell - 전체 구성도
다음 그래프에서 볼 수 있듯이 Cloud Shell 세션을 배포할 수 있는 각 리전은 수십 개의 IP 주소를 제공합니다. 사용자는 IP 풀을 늘리기 위해 여러 리전을 동시에 구성할 수 있습니다.
그림 7: Azure Cloud Shell - 리전별 사용 가능한 IP 주소
그러나 IP 주소는 AWS API Gateway보다 더 집중되어 있습니다. 다음 지도에서 볼 수 있듯이 대부분 미국, 유럽, 인도에 위치해 있습니다.
그림 8: Azure Cloud Shell - 국가별 IP 주소
Cloud Shell 갱신 프로세스의 지연으로 인해 요청 흐름 속도를 제한할 것을 권장합니다. 자세한 내용은 런처 비교 하위 섹션을 참조하십시오.
IPSpinner는 요청 전송에 GitHub Actions를 활용할 수도 있습니다. 이 구현은 git-rotate에서 영감을 얻었지만 캐처(catcher) 서버를 제거하기 위해 완전히 수정되고 조정되었습니다.
미리 정의된 워크플로 템플릿이 포함된 리포지토리를 생성합니다. 그런 다음 각 요청에 대해 환경 변수를 통해 요청 정보를 전달하여 워크플로를 실행합니다. 모든 데이터는 외부 사용자가 읽을 수 없도록 암호화됩니다. 마지막으로 IPSpinner는 워크플로 로그에서 응답 데이터를 수집합니다.
그림 9: GitHub Actions - 전체 구성도
다음 그림은 GitHub Actions가 수천 개의 서로 다른 IP 주소를 제공한다는 것을 보여줍니다.
그림 10: GitHub Actions - 리전별 사용 가능한 IP 주소
그러나 다음 지도는 GitHub Actions가 미국 IP 주소만 제공한다는 것을 보여줍니다. 분석 결과, 해당 워커는 Azure 인프라에 배포된 것으로 보입니다.
그림 11: GitHub Actions - 국가별 IP 주소
⚠️ 또한, "GitHub는 Actions의 남용과 스팸을 심각하게 간주하며, '스팸성 사용자'를 추적하는 전담 팀을 두고 있습니다." 따라서 사용자는 계정 폐쇄 문제를 피하기 위해 자신의 계정이나 회사 계정으로 이 공급자를 사용해서는 안 됩니다.
GitHub REST API의 시간당 제한으로 인해 중단을 피하려면 최대 요청 흐름 속도를 제한해야 합니다. 자세한 내용은 런처 비교 하위 섹션을 참조하십시오.
이 프로젝트는 go 버전 >= 1.21에서 테스트되었지만, 더 낮은 go 버전에서도 작동할 수 있습니다.
Go 설치 문서를 참조하십시오.
설치 후 기본 go 바이너리가 올바른 버전인지 확인하십시오:
$ go version
go version go1.21.1 linux/amd64
$ git clone https://github.com/synacktiv/IPSpinner.git
$ cd IPSpinner
$ go mod tidy
$ make build-linux # For Linux AMD64 arch
$ make build-windows # For Windows AMD64 arch
실행 파일은 Linux에서는 기본적으로 "ipspinner", Windows에서는 "ipspinner.exe"라는 이름으로 생성됩니다.
사용이 끝나면 다음 명령으로 빌드를 정리할 수 있습니다
$ make clean
IPSpinner 사용에 대한 도움말을 보려면 인자 없이 명령을 실행할 수 있습니다:
$ ./ipspinner -h
Help will be displayed
모든 정보(요청 리디렉션 제외)는 ipspinner.log 파일에 기록됩니다.
일부 일반적인 옵션은 인자로 사용할 수 있으며, 기타 구성 정보는 INI 구성 파일에 제공해야 합니다.
사용자는 다음 명령줄 인자를 지정할 수 있습니다:
일부 전역 및 공급자 매개변수는 INI 구성 파일에 지정해야 합니다. 구성 파일은 IPSpinner를 실행하기 전에 준비해야 합니다. 해당 내용은 다음 하위 섹션에서 설명합니다. 기본적으로 IPSpinner는 config.ini라는 이름의 구성 파일을 찾습니다.
HTTPS 요청을 처리하기 위해 IPSpinner는 인증 기관(CA) 인증서와 키가 필요합니다. 사용자가 인증서를 제공하지 않으면 IPSpinner는 자체 서명된 인증서와 키를 생성합니다. 사용자는 --export-ca-cert를 사용하여 생성된 인증서를 내보낼 수 있습니다(예: 브라우저에 가져오기 위해). 그렇지 않으면 사용자는 구성 파일에 자체 CA 인증서와 키를 제공할 수 있습니다(다음 부분 참조).
사용자는 --host 및 --port로 수신 호스트와 포트를 지정할 수 있습니다.
마지막으로 세 가지 상세(verbose) 모드를 사용할 수 있습니다:
또한 프로젝트 리포지토리에는 INI 구성 파일용 템플릿이 제공됩니다.
proxy 섹션에서 사용자는 다음 매개변수를 지정할 수 있습니다:
기타 모든 섹션은 해당 공급자 장에서 설명합니다.
사용자가 여러 공급자와 런처를 동시에 활성화할 수 있다는 점을 알아두는 것이 중요합니다. 그러면 IPSpinner는 각 요청에 대해 사용 가능한 모든 런처 중에서 무작위 런처를 선택합니다.
aws 섹션의 AWS 구성 매개변수:
aws 섹션의 API Gateway 구성 매개변수:
azure 섹션의 Azure 구성 매개변수:
azure 섹션의 Azure Cloud Shell 구성 매개변수:
github 섹션의 GitHub 구성 매개변수:
| 매개변수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| username | ✅ | GitHub 사용자 이름 | |
| token | ✅ | 제공된 사용자 이름과 연결된 GitHub 토큰 |
github 섹션의 GitHub Actions 구성 매개변수:
| 매개변수 | 필수 (ga_enabled=true인 경우) | 기본값 | 설명 |
|---|---|---|---|
| ga_enabled | / | GitHub Actions 런처 활성화 |
IPSpinner는 HTTP/2 프로토콜을 지원하지 않습니다. 프록시가 첫 번째 TLS 연결을 종료하므로 프로토콜의 장점은 사라지고 기본 HTTP/1.1 연결로 나타납니다.
따라서 Burp Suite와 함께 IPSpinner를 사용할 때 HTTP/2 문제를 피하려면 HTTP/2 클라이언트 지원을 제거하십시오: Settings > Network > HTTP > HTTP/2 > HTTP/2 확인란의 선택을 해제하십시오.
| AWS API Gateway | Azure Cloud Shell | GitHub Actions |
|---|
| 사용 가능한 IP 주소 | ≈ 12,418 | ≈ 276 | > 6,000 |
| 평균 응답 시간 | 0.46s | 13.04s | 21.42s |
| 평균 재구성 시간 | 없음 | 20s | 없음 |
| 이론상 최대 요청 속도 | 4,000 to 16,000 req/h | 107 req/h/cloud shell instance | 1,000 req/h |
| 프리로드 가능/필요 여부? | ✅ | ❌ | ❌ |
| 용도: 브라우징 | ✅ | ❌ | ❌ |
| 용도: 패스워드 스프레이 | ✅ | ✅ | ✅ |
| 매개변수 | 필수 | 기본값 |
|---|
| --config | ❌ | config.ini |
| --export-ca-cert | ❌ | |
| --host | ❌ | |
| --port | ❌ | 8080 |
| --v, --vv, --vvv | ❌ |
| 매개변수 | 필수 | 기본값 | 설명 |
|---|
| preload_hosts_file | ❌ | 호스트를 프리로드할 수 있는 공급자를 위해 프리로드할 URL/호스트 목록 | |
| whitelist_hosts_file | ❌ | 화이트리스트에 등록된 URL/호스트 목록(기본적으로 다른 모든 항목은 블랙리스트에 등록됨) | |
| blacklist_hosts_file | ❌ | 블랙리스트에 등록된 URL/호스트 목록(화이트리스트가 설정된 경우 무시됨) | |
| ca_cert_file & ca_cert_key_file | ❌ | 사용자가 제공하는 CA 인증서(기본 생성 인증서를 교체하려는 경우) | |
| user_agents_file | ❌ | 요청에 대해 무작위로 선택될 사용자 에이전트 목록 | |
| debug_response_headers | ❌ | false | 프록시 응답에 두 개의 디버그 헤더를 추가합니다: X-IPSpinner-Provider 및 X-IPSpinner-Provider-NbTotalReqSent |
| wait_for_launcher_available_timeout | ❌ | 60 | 사용 가능한 런처가 없을 때 요청이 타임아웃되기까지의 시간(초) |
| 매개변수 | 필수 | 기본값 | 설명 |
|---|
| regions | ✅ | 리소스를 배포할 수 있는 리전 목록(쉼표로 구분) | |
| profile | ❌ | 사용할 AWS CLI 프로필 | |
| access_key | ✅ (또는 profile) | AWS 사용자 액세스 키 | |
| secret_key | ✅ (또는 profile) | AWS 사용자 시크릿 키 | |
| session_token | ❌ | AWS 사용자 세션 토큰 |
| 매개변수 | 필수 (ag_enabled=true인 경우) | 기본값 | 설명 |
|---|
| ag_enabled | / | API Gateway 런처 활성화 | |
| ag_max_instances | ❌ | 5 | 배포할 수 있는 최대 API Gateway 인스턴스 수(리전별이 아닌 전체 최대값) |
| ag_rotate_nb_requests | ❌ | 5,000 | API Gateway를 회전시키기 전까지의 요청 수 |
| ag_forwarded_for_range | ❌ | 35.180.0.0/16 | X-Forwarded-For 헤더용 IP 주소 범위(IPv4 또는 IPv6 범위) |
| ag_instance_title_prefix | ❌ | fpr | API Gateway 정보 사용자 지정 |
| ag_instance_deployment_description | ❌ | IPSpinner FireProx Prod | API Gateway 정보 사용자 지정 |
| ag_instance_deployment_stage_description | ❌ | IPSpinner FireProx Prod Stage | API Gateway 정보 사용자 지정 |
| ag_instance_deployment_stage_name | ❌ | 영어 단어 3개 무작위 | API Gateway 정보 사용자 지정 |
| 매개변수 | 필수 | 기본값 | 설명 |
|---|
| admin_email | ✅ (또는 accounts_file) | Azure 관리자 이메일 | |
| admin_password | ✅ (또는 accounts_file) | Azure 관리자 비밀번호 | |
| tenant_id | ✅ | 테넌트 ID | |
| subscription_id | ✅ | 구독 ID | |
| accounts_file | ❌ | admin_email 및 admin_password를 재정의하는 사전 생성된 계정 목록(이메일과 비밀번호, 줄당 하나의 정보) |
| 매개변수 | 필수 (cs_enabled=true인 경우) | 기본값 | 설명 |
|---|
| cs_enabled | / | Cloud Shell 런처 활성화 | |
| cs_preferred_locations | ✅ | Cloud Shell 인스턴스를 배포할 위치 | |
| cs_nb_instances | ❌ | 5 | 배포할 Cloud Shell 인스턴스 수 |