fae4daeebe0cbf0c4efd153137bcaf379e67d441
- XHTTP 설정 가이드 - Reality 설정 가이드 - TLS 검열 우회 원리 - 트러블슈팅 가이드
Xray 프록시 완벽 가이드: XHTTP & Reality
검열 우회를 위한 스텔스 프록시 구축 가이드
참고 영상: How to Hide a Proxy Inside a Real Website (Xray + XHTTP) - LinuxCloudHacks
목차
핵심 개념
현대 검열의 문제점
기존 VPN/프록시가 차단되는 이유:
| 방식 | 탐지 방법 |
|---|---|
| 일반 VPN | VPN 프로토콜 시그니처 탐지 |
| Shadowsocks | 랜덤 노이즈 패턴 → DPI가 "비정상" 판단 |
| 단순 프록시 | 특이한 포트, 서버 프로빙 시 프록시 응답 |
해결책: 섞여들기 (Blending In)
"현대 검열은 숨김으로 이기는 게 아니라, 섞여들어감으로 이긴다"
- 일반 HTTPS 트래픽처럼 보이게 위장
- 실제 웹사이트 또는 대형 사이트의 TLS를 활용
- 클라이언트와 서버 양쪽 모두 위장 필요
프로토콜 스택 이해
3계층 구조
┌─────────────────────────────────────────┐
│ TLS (누구처럼) │
│ - 암호화 │
│ - 핑거프린트 위장 (UTLS → Chrome 흉내) │
├─────────────────────────────────────────┤
│ XHTTP (어떻게) │
│ - HTTP POST/GET으로 데이터 전송 │
│ - 일반 API 트래픽처럼 보임 │
├─────────────────────────────────────────┤
│ VLESS (무엇을) │
│ - 프록시 프로토콜 │
│ - 경량, 상태 비저장 │
│ - UUID 기반 인증 │
└─────────────────────────────────────────┘
VLESS 프레임 구조
[버전][클라이언트ID][명령][포트][주소타입][주소][페이로드...]
1B 16B 1B 2B 1B 가변 가변
- 명령: 1=TCP, 2=UDP
- 주소타입: 1=IPv4, 2=도메인, 3=IPv6
- 암호화 없음 → 전송 계층(TLS)에서 처리
XHTTP 동작 방식
클라이언트 → 서버: HTTP POST (세션ID + VLESS 프레임)
서버 → 클라이언트: HTTP GET (스트리밍 응답)
- 세션 ID로 다중 연결 관리
- 병렬 POST 요청 가능 (Head-of-line blocking 회피)
- 일반 REST API 호출처럼 보임
XHTTP 설정
아키텍처
[클라이언트]
↓ HTTPS (일반 브라우저처럼 보임)
[Nginx - Port 443]
├── / (루트) → 실제 게임 웹사이트
└── /api/stream (비밀 경로) → Xray (Port 8080)
↓
[인터넷]
준비물
- Linux 서버 (VPS/클라우드)
- 도메인 (필수)
- DNS 제공자 (Cloudflare 등)
- 포트 80, 443 오픈
서버 설정
1. Nginx + Certbot 설치
apt update && apt install -y nginx certbot python3-certbot-nginx
2. 위장용 웹사이트 배포
# 기본 페이지 삭제 후 게임 템플릿 다운로드
rm /var/www/html/index.html
wget -O /var/www/html/index.html https://example.com/game-template.html
3. SSL 인증서 발급
certbot certonly --webroot -w /var/www/html -d yourdomain.com
4. Xray 설치
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
5. UUID 생성
xray uuid
# 출력 예: a3482e88-686a-4a58-8126-99c9df64b060
6. Xray 서버 설정
/usr/local/etc/xray/config.json:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 8080,
"listen": "127.0.0.1",
"protocol": "vless",
"settings": {
"clients": [
{
"id": "여기에-UUID-입력"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"path": "/api/stream"
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
7. Nginx 설정
/etc/nginx/sites-available/xray:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# 루트: 실제 웹사이트 (위장용)
location / {
root /var/www/html;
index index.html;
}
# 비밀 경로: Xray로 프록시
location /api/stream {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 300s;
}
}
ln -sf /etc/nginx/sites-available/xray /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx
systemctl restart xray
클라이언트 설정
CLI (config.json)
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 1080,
"listen": "127.0.0.1",
"protocol": "socks"
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "yourdomain.com",
"port": 443,
"users": [
{
"id": "서버와-동일한-UUID",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "xhttp",
"security": "tls",
"tlsSettings": {
"serverName": "yourdomain.com",
"fingerprint": "chrome"
},
"xhttpSettings": {
"path": "/api/stream"
}
}
}
]
}
V2rayN GUI 설정
| 항목 | 값 |
|---|---|
| Address | yourdomain.com |
| Port | 443 |
| UUID | 서버와 동일 |
| Network | xhttp |
| Path | /api/stream |
| TLS | 활성화 |
| SNI | yourdomain.com |
| Fingerprint | chrome |
Reality 설정
Reality란?
도메인/인증서 없이, 대형 사이트의 TLS를 빌려 쓰는 기술
[클라이언트] --TLS(SNI: www.microsoft.com)--> [내 서버:443]
↓
Reality가 TLS 처리
(microsoft.com 인증서 흉내)
↓
[인터넷]
외부에서 보이는 것: www.microsoft.com에 접속
실제: 내 VPS를 통해 터널링
준비물
- Linux 서버 (VPS/클라우드)
- 포트 443 오픈
- 도메인 불필요!
서버 설정
1. Xray 설치
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
2. 키 생성
# UUID 생성
xray uuid
# 출력 예: a3482e88-686a-4a58-8126-99c9df64b060
# X25519 키쌍 생성
xray x25519
# 출력 예:
# Private key: 2KZ4uouMKgI8nR-LDJNP1_MHisCJOmKGj9jUjZLncVU
# Public key: Z84J2IelR9ch3k8VtlVhhs5ycBUlXA7wHBWcBrjqnAw
# Short ID 생성
openssl rand -hex 8
# 출력 예: 6ba85179e30d4fc2
3. 위장 사이트 선택
선택 기준:
| 조건 | 설명 |
|---|---|
| 외국 사이트 | 검열 대상이 아닌 사이트 |
| TLSv1.3 지원 | 필수 |
| H2 지원 | HTTP/2 지원 필요 |
| 리다이렉트 없음 | URL이 다른 곳으로 이동하지 않음 |
| 서버와 가까운 지역 | 보너스 (속도 향상) |
추천 사이트:
www.microsoft.comwww.apple.comwww.amazon.comwww.cloudflare.comwww.yahoo.com
4. 서버 설정 파일
/usr/local/etc/xray/config.json:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "여기에-UUID-입력",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "www.microsoft.com:443",
"serverNames": [
"www.microsoft.com",
"microsoft.com"
],
"privateKey": "여기에-Private-Key-입력",
"shortIds": [
"여기에-Short-ID-입력"
]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
}
]
}
systemctl restart xray
systemctl status xray
클라이언트 설정
CLI (config.json)
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 1080,
"protocol": "socks"
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "서버-IP-주소",
"port": 443,
"users": [
{
"id": "서버와-동일한-UUID",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"fingerprint": "chrome",
"serverName": "www.microsoft.com",
"publicKey": "서버의-Public-Key",
"shortId": "서버와-동일한-Short-ID"
}
},
"tag": "proxy"
},
{
"protocol": "freedom",
"tag": "direct"
}
]
}
V2rayN GUI 설정
| 항목 | 값 |
|---|---|
| Address | 서버 IP |
| Port | 443 |
| UUID | 생성한 UUID |
| Flow | xtls-rprx-vision |
| Network | tcp |
| TLS | reality |
| SNI | www.microsoft.com |
| Fingerprint | chrome |
| Public Key | 서버에서 생성한 공개키 |
| Short ID | 서버와 동일 |
Docker로 설정 (간편)
docker-compose.yml
services:
xray:
image: ghcr.io/xtls/xray-core:latest
container_name: xray-reality
restart: unless-stopped
volumes:
- ./config.json:/usr/local/etc/xray/config.json:ro
ports:
- "443:443/tcp"
키 생성 (Docker)
docker run --rm ghcr.io/xtls/xray-core x25519
docker run --rm ghcr.io/xtls/xray-core uuid
실행
docker compose up -d
XHTTP vs Reality 비교
기능 비교
| 구분 | XHTTP | Reality |
|---|---|---|
| 도메인 | 필요 | 불필요 |
| SSL 인증서 | 필요 (Let's Encrypt) | 불필요 |
| Nginx | 필요 | 불필요 |
| 설정 시간 | 30분+ | 5분 |
| CDN 통과 | 가능 | 불가 |
| 위장 방식 | 실제 웹사이트 운영 | 대형 사이트 TLS 흉내 |
| SNI 노출 | 내 도메인 | 대형 사이트 (microsoft.com 등) |
사용 시나리오
Reality 사용
| 상황 | 이유 |
|---|---|
| 도메인 없음 | 도메인 구매/관리 불필요 |
| 빠른 설정 | 키 생성만으로 완료 |
| VPS만 있음 | IP 하나로 바로 시작 |
| 단순 우회 목적 | 복잡한 구성 불필요 |
| SNI 노출 걱정 | 대형 사이트로 위장 |
XHTTP 사용
| 상황 | 이유 |
|---|---|
| CDN 필요 | Cloudflare 등 CDN 뒤에 숨기기 |
| IP 차단 환경 | VPS IP가 이미 차단된 경우 |
| 실제 서비스 운영 | 웹사이트 + 프록시 동시 운영 |
| 다수 사용자 | 여러 명에게 서비스 제공 |
| 서버 프로빙 대응 | 443 접속 시 실제 웹사이트 표시 |
결정 가이드
도메인이 없다 ──────────────────→ Reality
│
↓ 있다
VPS IP가 차단됐다 ─────────────→ XHTTP + CDN
│
↓ 아니다
SNI 노출이 걱정된다 ───────────→ Reality
│
↓ 괜찮다
실제 웹사이트도 운영할 것이다 ──→ XHTTP
│
↓ 아니다
빠른 설정을 원한다 ────────────→ Reality
TLS와 검열 우회 원리
TLS 핸드셰이크 구조
[클라이언트] [서버]
│ │
│─── Client Hello ──────────→│ 평문! (SNI 노출)
│ │
│←── Server Hello ───────────│
│←── Certificate ────────────│
│←── Server Key Exchange ────│
│ │
│─── Client Key Exchange ───→│
│─── Finished ──────────────→│
│ │
│←── Finished ───────────────│
│ │
[암호화 통신 시작]
Client Hello 구조
TLS Record Layer
├── Content Type: 0x16 (Handshake)
├── Version: 0x0301
└── Handshake Protocol
├── Type: 0x01 (Client Hello)
└── Client Hello Data
├── Version: 0x0303 (TLS 1.2)
├── Random: 32바이트
├── Session ID
├── Cipher Suites (암호화 목록)
├── Compression Methods
└── Extensions
├── SNI (server_name) ← 평문 노출!
├── Supported Versions
├── Signature Algorithms
└── ...
SNI 노출 문제
**SNI(Server Name Indication)**는 TLS 암호화 전에 평문으로 전송됨:
Extension: server_name
├── Type: 0x0000 (SNI)
└── Server Name
└── Name: "www.microsoft.com" ← ISP가 볼 수 있음
| 방식 | SNI에 보이는 것 | 위험도 |
|---|---|---|
| XHTTP | myproxy.com (내 도메인) |
도메인 차단 가능 |
| Reality | www.microsoft.com |
차단 어려움 |
DPI 핑거프린팅
검열 시스템이 Client Hello를 분석하는 방식:
Client Hello 수신
↓
특징 추출:
- Cipher Suite 개수 및 순서
- Extension 목록 및 순서
- Supported Groups
- 전체 패킷 길이
↓
데이터베이스 비교:
- Chrome: 일치 ✓
- Firefox: 불일치
- Python requests: 불일치
↓
결과: "Chrome 브라우저로 판단"
UTLS를 통한 위장
Xray는 UTLS 라이브러리를 사용하여 실제 브라우저의 Client Hello를 바이트 단위로 복제:
{
"tlsSettings": {
"fingerprint": "chrome" // Chrome의 정확한 핑거프린트 사용
}
}
복제하는 요소:
- Cipher Suites (암호화 알고리즘 목록 + 순서)
- Extensions (확장 목록 + 순서)
- Supported Groups (지원 곡선)
- Signature Algorithms (서명 알고리즘)
- ALPN (프로토콜 협상)
- Key Share (키 교환 데이터)
서버 측 위장의 필요성
양방향 모두 위장 필요:
| 방향 | 검사 대상 | 위장 주체 |
|---|---|---|
| Client → Server | Client Hello, SNI | 클라이언트 (UTLS) |
| Server → Client | 인증서, Server Hello | 서버 설정 |
Reality 서버의 프로빙 대응
정상 클라이언트 (올바른 shortId/publicKey):
↓
서버: "인증된 클라이언트"
↓
Reality 터널 연결 ✓
프로빙/스캐너 (shortId 없음):
↓
서버: "모르는 요청"
↓
실제 microsoft.com으로 포워딩
↓
스캐너: "그냥 microsoft.com이네" → 의심 없음
XHTTP 서버의 프로빙 대응
일반 접속 (루트 경로):
↓
Nginx: 게임 웹사이트 표시 ✓
프록시 클라이언트 (비밀 경로):
↓
Nginx: Xray로 프록시 ✓
트러블슈팅
공통 문제
| 문제 | 원인 | 해결 |
|---|---|---|
| 연결 안됨 | 방화벽 | 443 포트 오픈 확인 |
| 인증 실패 | UUID 불일치 | 서버/클라이언트 UUID 동일한지 확인 |
| 느린 속도 | 서버 위치 | 더 가까운 VPS 선택 |
XHTTP 문제
| 문제 | 원인 | 해결 |
|---|---|---|
| 502 Bad Gateway | Xray 미실행 | systemctl status xray 확인 |
| SSL 에러 | 인증서 만료 | certbot renew 실행 |
| 경로 불일치 | path 설정 | Nginx와 Xray의 path 동일한지 확인 |
Reality 문제
| 문제 | 원인 | 해결 |
|---|---|---|
| TLS 에러 | 위장 사이트 문제 | TLSv1.3 지원 사이트로 변경 |
| shortId 에러 | ID 불일치 | 서버/클라이언트 shortId 확인 |
| 키 에러 | 공개키/개인키 혼동 | 서버=개인키, 클라이언트=공개키 |
연결 테스트
# 서버에서 Xray 상태 확인
systemctl status xray
journalctl -u xray -f
# 클라이언트에서 연결 테스트
curl -x socks5h://127.0.0.1:1080 https://ipinfo.io
참고 자료
공식 문서
튜토리얼
- Xray REALITY Tutorial - cscot
- XRAY XTLS Reality in Docker
- XRAY XHTTP Behind Cloudflare CDN
- Coexisting Xray VLESS with XHTTP-Reality
GitHub Discussions
클라이언트 앱
부록: 빠른 설정 체크리스트
Reality 설정 (5분)
- VPS 준비 (포트 443 오픈)
- Xray 설치
- UUID 생성
- X25519 키쌍 생성
- Short ID 생성
- 서버 config.json 작성
- 클라이언트 설정
XHTTP 설정 (30분)
- VPS 준비 (포트 80, 443 오픈)
- 도메인 준비 + DNS 설정
- Nginx 설치
- 위장용 웹사이트 배포
- Certbot으로 SSL 인증서 발급
- Xray 설치
- UUID 생성
- Xray config.json 작성
- Nginx 설정 (루트 + 비밀 경로)
- 클라이언트 설정
마지막 업데이트: 2025-01