Files
xray-proxy-guide/README.md
kappa fae4daeebe Initial commit: Xray 프록시 가이드 (XHTTP & Reality)
- XHTTP 설정 가이드
- Reality 설정 가이드
- TLS 검열 우회 원리
- 트러블슈팅 가이드
2026-01-12 11:57:32 +09:00

809 lines
19 KiB
Markdown

# Xray 프록시 완벽 가이드: XHTTP & Reality
> 검열 우회를 위한 스텔스 프록시 구축 가이드
>
> 참고 영상: [How to Hide a Proxy Inside a Real Website (Xray + XHTTP)](https://www.youtube.com/watch?v=NziF6Srh-08) - LinuxCloudHacks
---
## 목차
1. [핵심 개념](#핵심-개념)
2. [프로토콜 스택 이해](#프로토콜-스택-이해)
3. [XHTTP 설정](#xhttp-설정)
4. [Reality 설정](#reality-설정)
5. [XHTTP vs Reality 비교](#xhttp-vs-reality-비교)
6. [TLS와 검열 우회 원리](#tls와-검열-우회-원리)
7. [트러블슈팅](#트러블슈팅)
8. [참고 자료](#참고-자료)
---
## 핵심 개념
### 현대 검열의 문제점
기존 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 설치
```bash
apt update && apt install -y nginx certbot python3-certbot-nginx
```
#### 2. 위장용 웹사이트 배포
```bash
# 기본 페이지 삭제 후 게임 템플릿 다운로드
rm /var/www/html/index.html
wget -O /var/www/html/index.html https://example.com/game-template.html
```
#### 3. SSL 인증서 발급
```bash
certbot certonly --webroot -w /var/www/html -d yourdomain.com
```
#### 4. Xray 설치
```bash
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
```
#### 5. UUID 생성
```bash
xray uuid
# 출력 예: a3482e88-686a-4a58-8126-99c9df64b060
```
#### 6. Xray 서버 설정
`/usr/local/etc/xray/config.json`:
```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`:
```nginx
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;
}
}
```
```bash
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)
```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
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
```
#### 2. 키 생성
```bash
# 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.com`
- `www.apple.com`
- `www.amazon.com`
- `www.cloudflare.com`
- `www.yahoo.com`
#### 4. 서버 설정 파일
`/usr/local/etc/xray/config.json`:
```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"
}
]
}
```
```bash
systemctl restart xray
systemctl status xray
```
### 클라이언트 설정
#### CLI (config.json)
```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
```yaml
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)
```bash
docker run --rm ghcr.io/xtls/xray-core x25519
docker run --rm ghcr.io/xtls/xray-core uuid
```
#### 실행
```bash
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를 **바이트 단위로** 복제:
```json
{
"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 확인 |
| 키 에러 | 공개키/개인키 혼동 | 서버=개인키, 클라이언트=공개키 |
### 연결 테스트
```bash
# 서버에서 Xray 상태 확인
systemctl status xray
journalctl -u xray -f
# 클라이언트에서 연결 테스트
curl -x socks5h://127.0.0.1:1080 https://ipinfo.io
```
---
## 참고 자료
### 공식 문서
- [Project X 공식 문서](https://xtls.github.io/en/config/)
- [XTLS/Xray-core GitHub](https://github.com/XTLS/Xray-core)
### 튜토리얼
- [Xray REALITY Tutorial - cscot](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/)
- [XRAY XTLS Reality in Docker](https://linuxguidance.net/xray-xtls-reality-in-docker/)
- [XRAY XHTTP Behind Cloudflare CDN](https://linuxguidance.net/xray-xhttp-server-behind-cloudflares-cdn-in-docker/)
- [Coexisting Xray VLESS with XHTTP-Reality](https://henrywithu.com/coexisting-xray-vless-tcp-xtls-vision-and-vless-xhttp-reality-on-a-single-port/)
### GitHub Discussions
- [VLESS + TCP + REALITY + VISION 설정](https://github.com/XTLS/Xray-core/discussions/3518)
- [Xray + VLESS + Reality + Caddy](https://github.com/XTLS/Xray-core/discussions/4542)
### 클라이언트 앱
- **Windows**: [v2rayN](https://github.com/2dust/v2rayN)
- **macOS**: [V2rayU](https://github.com/yanue/V2rayU)
- **Android**: [v2rayNG](https://github.com/2dust/v2rayNG)
- **iOS**: Shadowrocket (유료), Quantumult X
---
## 부록: 빠른 설정 체크리스트
### 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*