NaiveProxy: Chromium 기반 VLESS의 안전한 대안
공격적인 차단 노력 속에서 NaiveProxy 프로토콜은 Chromium의 원본 네트워킹 스택을 활용한 독특한 트래픽 위장 방식을 제공합니다. sing-box와 Caddy를 사용해 클라이언트와 서버 설정 과정을 안내하며, 흔한 함정을 피해 나가겠습니다.
트래픽 위장 기본: 왜 NaiveProxy가 uTLS를 이길까?
표준 프록시 프로토콜은 HTTPS 트래픽으로 위장하지만, 초기 ClientHello 패킷은 여전히 취약합니다. TLS 버전, 암호화 목록, 도메인을 평문으로 전송하죠. Go 기반 구현체(포함 Xray와 sing-box)는 언어 고유의 ClientHello 지문을 가지고 있어 uTLS를 써도 식별 가능합니다. uTLS 라이브러리는 첫 패킷에서만 브라우저 동작을 모방할 뿐, 데이터 전송 리듬, 프레임 길이, HTTP/2 특성 같은 네트워크 스택 미묘함을 재현하지 못합니다. NaiveProxy는 Chromium 조각을 내장해 완벽한 브라우저 트래픽 에뮬레이션을 제공합니다.
NaiveProxy 아키텍처: Chromium에서 프록시까지
프로토콜 창시자 klzgrad는 Chromium 소스 코드를 0.3% 기능만 남겨 네트워킹에 필요한 부분만 추출했습니다. 주요 특징:
- Chromium의 네이티브 HTTP/2 스택으로 멀티플렉싱 사용
- ClientHello와 후속 패킷이 실제 브라우저 트래픽과 완벽 일치
- 커스텀 암호 대신 표준 TLS 메커니즘 사용
중요: 양방향으로 표준 HTTP/2 프록시와 완벽 호환됩니다. Naive 클라이언트는 모든 HTTP/2 프록시와 작동하고, Naive 서버는 표준 클라이언트 연결을 수락합니다. 하지만 진짜 위장은 Chromium 네트워크 스택(예: sing-box)에서만 이뤄집니다. 다른 클라이언트(예: Go 기반)는 Naive 서버에 연결할 수 있지만 완전한 익명성을 제공하지 않습니다.
패딩: 트래픽 분석에 대한 3중 보호
프로토콜은 패킷 길이 분석을 막기 위해 다단계 패딩을 사용합니다:
- DATA 프레임: 각 스트림의 처음 8개 프레임에 헤더(데이터 길이 2바이트 + 패딩 길이 1바이트)를 추가한 후 원본 데이터와 패딩 바이트를 붙입니다.
- CONNECT 요청: 랜덤 길이 헤더로 프레임 크기를 임의로 키웁니다.
- END_STREAM: 각 RST_STREAM 전에 추가 프레임을 삽입합니다.
테스트에서 sing-box의 치명적 결함이 드러났습니다: 패딩 추가 시 버퍼를 0으로 초기화하지 않고 이전 요청의 잔여 데이터를 보냈습니다. 이로 도메인 이름과 헤더 같은 민감 정보가 유출됐죠. 두 PR 병합 후 버퍼 강제 0 초기화로 1.13.1+ 버전에서 수정됐습니다.
클라이언트 설정: sing-box Outbound
sing-box 1.13+ 필요. 클라이언트 설정:
{
"type": "naive",
"tag": "Proxy1",
"server": "1.2.3.4",
"server_port": 443,
"username": "username",
"password": "password",
"insecure_concurrency": 1,
"udp_over_tcp": {
"enabled": true
},
"quic": false,
"tls": {
"enabled": true,
"server_name": "s1.example.com"
}
}
주요 매개변수:
insecure_concurrency: 1로 유지. 높이면 트래픽 분석이 쉬워집니다.udp_over_tcp: UDP 지원을 위해 활성화.server_name: Caddy에서 설정한 도메인. TLS 섹션의 server_name과 일치해야 합니다.
Caddy를 TLS 종료기로: 설정과 대체
Caddy는 TLS 연결을 처리하고 트래픽을 프록시나 미끼로 라우팅합니다. 설정(/etc/caddy/Caddyfile):
{
email [email protected]
auto_https disable_redirects
}
:443, https://s1.example.com {
tls {
issuer acme {
disable_http_challenge
}
}
route {
@naive {
method CONNECT
header Proxy-Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
}
handle @naive {
reverse_proxy h2c://127.0.0.1:1080 {
header_up Proxy-Authorization {header.Proxy-Authorization}
}
}
handle {
root * /srv/naive-fallback
file_server
}
}
}
주요 포인트:
Proxy-Authorization헤더에 base64 인코딩된username:password포함(echo -n "username:password" | base64로 생성)./srv/naive-fallback디렉터리에 스캔 방어용 정적 미끼 사이트 배치.auto_https disable_redirects로 443 포트 HTTPS 전용이므로 HTTP→HTTPS 리다이렉트 생략.
서버 측: sing-box Inbound와 Caddy 통합
서버 sing-box 설정(/etc/sing-box/config.json):
{
"log": {
"level": "warn",
"output": "/var/log/sing-box/sing-box.log"
},
"inbounds": [
{
"type": "naive",
"tag": "naive-in",
"network": "tcp",
"listen": "127.0.0.1",
"listen_port": 1080,
"users": [
{
"username": "username",
"password": "password"
}
]
}
],
"outbounds": [
{
"type": "direct"
}
]
}
중요:
- 서버는 Caddy가 외부 연결 처리하므로 localhost:1080만 수신.
warn로그 레벨로 디스크 I/O 최소화.- 비밀번호는 클라이언트와 Caddy 설정과 정확히 일치해야 합니다.
주요 요점
- 완전 위장은 Chromium 스택 필요: 원본 네트워크 코드 사용하는 구현체(예: sing-box)만 브라우저 트래픽과 완벽 일치.
- 동시성 = 위험:
insecure_concurrency1 초과 시 패킷 길이 분석 취약. - 컴포넌트 최신화: 패딩 데이터 유출 수정 위해 sing-box 1.13.1+ 사용.
- 미끼 사이트 필수: Caddy의 정적 사이트로 스캔으로부터 프록시 숨김.
- 현실은 완벽하지 않음: Reality 역사처럼 영리한 해법도 새 지문(예: 연결 수)으로 차단될 수 있습니다.
— Editorial Team
아직 댓글이 없습니다.