Created
March 31, 2026 14:20
-
-
Save moozd/0a005e1cd1205606c89c4dfc2beaeea6 to your computer and use it in GitHub Desktop.
glue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| # ─── Colors ─────────────────────────────────────────────────────────────────── | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' | |
| info() { echo -e "${GREEN}[+]${NC} $1"; } | |
| warn() { echo -e "${YELLOW}[!]${NC} $1"; } | |
| error() { echo -e "${RED}[x]${NC} $1"; exit 1; } | |
| # ─── Root check ─────────────────────────────────────────────────────────────── | |
| [[ $EUID -ne 0 ]] && error "Run as root" | |
| # ─── No SNI: print existing configs and exit ────────────────────────────────── | |
| if [[ -z "$1" ]]; then | |
| CONFIG="/usr/local/etc/xray/config.json" | |
| OUTPUT_FILE="$HOME/vless-links.txt" | |
| if [[ -f "$OUTPUT_FILE" ]]; then | |
| echo "" | |
| cat "$OUTPUT_FILE" | |
| exit 0 | |
| elif [[ -f "$CONFIG" ]]; then | |
| warn "No saved links file found. Reading from config..." | |
| SERVER_IP=$(curl -s https://api.ipify.org) | |
| SNI=$(grep -o '"dest": "[^"]*"' "$CONFIG" | head -1 | cut -d'"' -f4 | cut -d: -f1) | |
| PUBLIC_KEY=$(grep -o '"Password (PublicKey)": "[^"]*"' "$CONFIG" 2>/dev/null | cut -d'"' -f4 || echo "not found — rerun with SNI to regenerate") | |
| SHORT_ID=$(grep -o '"shortIds": \["[^"]*"' "$CONFIG" | grep -o '"[^"]*"$' | tr -d '"') | |
| UUIDS=($(grep -o '"id": "[^"]*"' "$CONFIG" | cut -d'"' -f4)) | |
| BASE="security=reality&encryption=none&pbk=${PUBLIC_KEY}&fp=chrome&sni=${SNI}&sid=${SHORT_ID}&flow=xtls-rprx-vision&type=tcp" | |
| echo "" | |
| echo "========================================================" | |
| echo " Server IP : $SERVER_IP" | |
| echo " SNI : $SNI" | |
| echo " Short ID : $SHORT_ID" | |
| echo "========================================================" | |
| echo "" | |
| for i in "${!UUIDS[@]}"; do | |
| echo "Link $((i+1)):" | |
| echo " vless://${UUIDS[$i]}@${SERVER_IP}:443?${BASE}#REALITY-$((i+1))" | |
| echo "" | |
| done | |
| exit 0 | |
| else | |
| error "No existing config found. Run: $0 <sni-domain>" | |
| fi | |
| fi | |
| SNI="$1" | |
| # Strip protocol if user included it | |
| SNI=$(echo "$SNI" | sed 's|https\?://||' | sed 's|/.*||') | |
| # ─── Verify SNI ─────────────────────────────────────────────────────────────── | |
| info "Verifying SNI: $SNI" | |
| # Check DNS resolution | |
| if ! getent hosts "$SNI" > /dev/null 2>&1; then | |
| error "Cannot resolve $SNI — check the domain and try again" | |
| fi | |
| # Check port 443 reachable | |
| if ! timeout 5 bash -c "echo > /dev/tcp/$SNI/443" 2>/dev/null; then | |
| error "$SNI:443 is not reachable from this server" | |
| fi | |
| # Check TLS 1.3 support | |
| TLS_VERSION=$(echo | timeout 5 openssl s_client -connect "$SNI:443" -tls1_3 2>&1 | grep "Protocol" | awk '{print $3}') | |
| if [[ "$TLS_VERSION" != "TLSv1.3" ]]; then | |
| error "$SNI does not support TLS 1.3 (required for REALITY)" | |
| fi | |
| info "SNI verified: $SNI is reachable and supports TLS 1.3" | |
| # ─── Install dependencies ───────────────────────────────────────────────────── | |
| info "Installing dependencies..." | |
| apt-get update -qq | |
| apt-get install -y curl uuid-runtime openssl -qq | |
| # ─── Install Xray (skip if already installed) ───────────────────────────────── | |
| if command -v xray &>/dev/null; then | |
| warn "Xray already installed: $(xray version 2>&1 | head -1) — skipping installation" | |
| else | |
| info "Installing Xray..." | |
| bash -c "$(curl -sL https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install | |
| info "Xray installed" | |
| fi | |
| # ─── Generate keys ──────────────────────────────────────────────────────────── | |
| info "Generating keys..." | |
| KEYS=$(xray x25519) | |
| PRIVATE_KEY=$(echo "$KEYS" | grep "PrivateKey" | awk '{print $2}') | |
| PUBLIC_KEY=$(echo "$KEYS" | grep "Password" | awk '{print $2}') | |
| SHORT_ID=$(openssl rand -hex 8) | |
| SERVER_IP=$(curl -s https://api.ipify.org) | |
| # Generate 6 UUIDs | |
| UUIDS=() | |
| for i in {1..6}; do | |
| UUIDS+=("$(uuidgen)") | |
| done | |
| # ─── Build clients JSON ─────────────────────────────────────────────────────── | |
| CLIENTS_JSON="" | |
| for uuid in "${UUIDS[@]}"; do | |
| CLIENTS_JSON+="{\"id\": \"$uuid\", \"flow\": \"xtls-rprx-vision\"}," | |
| done | |
| CLIENTS_JSON="${CLIENTS_JSON%,}" # remove trailing comma | |
| # ─── Write config ───────────────────────────────────────────────────────────── | |
| info "Writing Xray config..." | |
| cat > /usr/local/etc/xray/config.json << EOF | |
| { | |
| "log": { | |
| "loglevel": "warning", | |
| "access": "/var/log/xray/access.log", | |
| "error": "/var/log/xray/error.log" | |
| }, | |
| "inbounds": [ | |
| { | |
| "listen": "0.0.0.0", | |
| "port": 443, | |
| "protocol": "vless", | |
| "settings": { | |
| "clients": [${CLIENTS_JSON}], | |
| "decryption": "none" | |
| }, | |
| "streamSettings": { | |
| "network": "tcp", | |
| "security": "reality", | |
| "realitySettings": { | |
| "show": false, | |
| "dest": "${SNI}:443", | |
| "xver": 0, | |
| "serverNames": ["${SNI}", "www.${SNI}"], | |
| "privateKey": "${PRIVATE_KEY}", | |
| "shortIds": ["${SHORT_ID}"] | |
| } | |
| }, | |
| "sniffing": { | |
| "enabled": true, | |
| "destOverride": ["http", "tls", "quic"] | |
| } | |
| } | |
| ], | |
| "outbounds": [ | |
| {"protocol": "freedom", "tag": "direct"}, | |
| {"protocol": "blackhole", "tag": "block"} | |
| ], | |
| "routing": { | |
| "domainStrategy": "IPIfNonMatch", | |
| "rules": [ | |
| { | |
| "type": "field", | |
| "ip": ["geoip:private"], | |
| "outboundTag": "block" | |
| } | |
| ] | |
| } | |
| } | |
| EOF | |
| # ─── Start service ──────────────────────────────────────────────────────────── | |
| info "Starting Xray service..." | |
| systemctl daemon-reload | |
| systemctl enable xray --quiet | |
| systemctl restart xray | |
| sleep 2 | |
| if ! systemctl is-active --quiet xray; then | |
| error "Xray failed to start — check: journalctl -u xray -n 30" | |
| fi | |
| info "Xray is running on port 443" | |
| # ─── Build links ────────────────────────────────────────────────────────────── | |
| BASE="security=reality&encryption=none&pbk=${PUBLIC_KEY}&fp=chrome&sni=${SNI}&sid=${SHORT_ID}&flow=xtls-rprx-vision&type=tcp" | |
| LINKS=() | |
| for i in "${!UUIDS[@]}"; do | |
| NUM=$((i + 1)) | |
| LINKS+=("vless://${UUIDS[$i]}@${SERVER_IP}:443?${BASE}#REALITY-${NUM}") | |
| done | |
| # ─── Save to file ───────────────────────────────────────────────────────────── | |
| OUTPUT_FILE="$HOME/vless-links.txt" | |
| { | |
| echo "VLESS+XTLS-REALITY Links" | |
| echo "Server: ${SERVER_IP} | SNI: ${SNI} | Port: 443" | |
| echo "Public Key: ${PUBLIC_KEY}" | |
| echo "Short ID: ${SHORT_ID}" | |
| echo "========================================================" | |
| echo "" | |
| for i in "${!LINKS[@]}"; do | |
| echo "Link $((i+1)):" | |
| echo "${LINKS[$i]}" | |
| echo "" | |
| done | |
| } > "$OUTPUT_FILE" | |
| # ─── Print results ──────────────────────────────────────────────────────────── | |
| echo "" | |
| echo -e "${GREEN}========================================================" | |
| echo " VLESS+XTLS-REALITY Setup Complete" | |
| echo -e "========================================================${NC}" | |
| echo " Server IP : $SERVER_IP" | |
| echo " SNI : $SNI" | |
| echo " Public Key : $PUBLIC_KEY" | |
| echo " Short ID : $SHORT_ID" | |
| echo "" | |
| for i in "${!LINKS[@]}"; do | |
| echo -e "${YELLOW}Link $((i+1)):${NC}" | |
| echo " ${LINKS[$i]}" | |
| echo "" | |
| done | |
| echo -e "${GREEN}Saved to: $OUTPUT_FILE${NC}" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment