From 60b613afc9639b939e4a2e466eb24a287eded0df Mon Sep 17 00:00:00 2001 From: SamNet-dev Date: Fri, 6 Feb 2026 20:49:49 -0600 Subject: [PATCH] feat: xray panel compatibility for GFK with setup guide When an existing xray panel is detected, skip SOCKS5 setup entirely since GFK is a raw TCP forwarder that works with any service on the target port. Warn users to configure Iran panel outbound accordingly. - Detect existing xray panel and skip SOCKS5 installation - Check all target ports in multi-port mappings and report status - Show clear ACTION REQUIRED warnings for Iran panel configuration - Panel-aware install summary (not misleading SOCKS5 message) - Clean up legacy standalone gfk-socks on reconfigure/uninstall - Use ss -tln (not -tlnH) for broader iproute2 compatibility - Add step-by-step panel setup guide in English and Farsi to README --- README.md | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ paqctl.sh | 103 +++++++++++++++++++++++++++--- 2 files changed, 276 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 23eef89..8886a11 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,97 @@ YOUR COMPUTER YOUR VPS INTERNET --- +
+Using GFK with an Existing Xray Panel (3x-ui, Marzban, etc.) + +If you already have an Xray panel on your server, GFK works alongside it without conflicts. GFK is a raw TCP forwarder — it tunnels traffic to whatever service is running on your target port. + +**How paqctl handles existing Xray:** + +| Scenario | What happens | +|---|---| +| **No Xray installed** | paqctl installs Xray with a SOCKS5 proxy automatically | +| **Xray panel running, target port is listening** | paqctl skips Xray setup, GFK forwards to your panel's inbound | +| **Xray running, target port NOT listening** | paqctl warns you — configure your panel to listen on that port | +| **Xray installed but not running** | paqctl installs its own SOCKS5 (same as fresh install) | + +**Step-by-step setup (panel on both servers):** + +Assume your **foreign server** has a panel with vmess/vless inbound on port `443`, and your **Iran server** has a panel with outbound to the foreign server. + +**1. Install paqctl on the foreign server (server role):** +```bash +curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash +``` +- Choose **server** role +- Set port mapping: `14000:443` (where `443` is your panel's inbound port) +- paqctl detects Xray is running and skips SOCKS5 — your panel stays untouched + +**2. Install paqctl on the Iran server (client role):** +```bash +curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash +``` +- Choose **client** role +- Set the **same** port mapping: `14000:443` +- Use the same auth code from the server setup + +**3. Update your Iran panel outbound to route through GFK:** + +In your Iran panel (3x-ui, Marzban, etc.), change the outbound that connects to the foreign server: + +**Before** (direct connection — blocked by DPI): +```json +{ + "tag": "vmess_out", + "protocol": "vmess", + "settings": { + "vnext": [{ + "address": "FOREIGN_SERVER_IP", + "port": 443, + "users": [{"id": "your-uuid", "security": "auto"}] + }] + } +} +``` + +**After** (routed through GFK tunnel): +```json +{ + "tag": "vmess_out", + "protocol": "vmess", + "settings": { + "vnext": [{ + "address": "127.0.0.1", + "port": 14000, + "users": [{"id": "your-uuid", "security": "auto"}] + }] + } +} +``` + +The key changes: +- `address`: from `FOREIGN_SERVER_IP` to `127.0.0.1` +- `port`: from `443` to `14000` (the VIO port from your mapping) + +**4. Traffic flow:** +``` +End user --> Iran panel inbound --> Iran panel outbound (127.0.0.1:14000) + --> GFK client (VIO port) --> QUIC tunnel over violated TCP + --> Foreign GFK server --> 127.0.0.1:443 (foreign panel inbound) --> Internet +``` + +**Multiple ports:** If your panel uses multiple ports, map them all: +``` +14000:443,14001:8080,14002:2020 +``` +Then create separate outbounds in your Iran panel for each port (14000, 14001, 14002). + +> **Note:** The "Firewall: VIO port blocked" status message (shown in green) is **normal and correct**. It means the firewall is properly configured for GFK's raw socket to work. + +
+ +--- + ## Quick Start ### 1. Server Setup (Linux VPS) @@ -1101,6 +1192,97 @@ MIT License - See [LICENSE](LICENSE) file. --- +
+استفاده از GFK با پنل Xray موجود (3x-ui، Marzban و غیره) + +اگر از قبل پنل Xray روی سرور خود دارید، GFK بدون تداخل در کنار آن کار می‌کند. GFK یک فورواردر خام TCP است — ترافیک را به هر سرویسی که روی پورت مقصد شما اجرا می‌شود تونل می‌کند. + +**رفتار paqctl با Xray موجود:** + +| سناریو | چه اتفاقی می‌افتد | +|---|---| +| **Xray نصب نیست** | paqctl به صورت خودکار Xray با پروکسی SOCKS5 نصب می‌کند | +| **پنل Xray در حال اجراست، پورت مقصد فعال است** | paqctl نصب Xray را رد می‌کند، GFK به اینباند پنل شما فوروارد می‌کند | +| **Xray در حال اجراست، پورت مقصد فعال نیست** | paqctl هشدار می‌دهد — پنل خود را روی آن پورت تنظیم کنید | +| **Xray نصب شده ولی اجرا نمی‌شود** | paqctl SOCKS5 خودش را نصب می‌کند (مثل نصب جدید) | + +**راهنمای گام به گام (پنل روی هر دو سرور):** + +فرض کنید **سرور خارج** پنلی با اینباند vmess/vless روی پورت `443` دارد و **سرور ایران** پنلی با اوتباند به سرور خارج دارد. + +**۱. نصب paqctl روی سرور خارج (نقش server):** +```bash +curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash +``` +- نقش **server** را انتخاب کنید +- مپینگ پورت: `14000:443` (که `443` پورت اینباند پنل شماست) +- paqctl تشخیص می‌دهد Xray در حال اجراست و نصب SOCKS5 را رد می‌کند — پنل شما دست نخورده می‌ماند + +**۲. نصب paqctl روی سرور ایران (نقش client):** +```bash +curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash +``` +- نقش **client** را انتخاب کنید +- **همان** مپینگ پورت: `14000:443` +- همان کد احراز هویت سرور را استفاده کنید + +**۳. اوتباند پنل ایران را به‌روزرسانی کنید تا از GFK عبور کند:** + +در پنل ایران (3x-ui، Marzban و غیره)، اوتباندی که به سرور خارج متصل می‌شود را تغییر دهید: + +**قبل** (اتصال مستقیم — توسط DPI مسدود می‌شود): +```json +{ + "tag": "vmess_out", + "protocol": "vmess", + "settings": { + "vnext": [{ + "address": "IP_SERVER_KHAREJ", + "port": 443, + "users": [{"id": "your-uuid", "security": "auto"}] + }] + } +} +``` + +**بعد** (از طریق تونل GFK): +```json +{ + "tag": "vmess_out", + "protocol": "vmess", + "settings": { + "vnext": [{ + "address": "127.0.0.1", + "port": 14000, + "users": [{"id": "your-uuid", "security": "auto"}] + }] + } +} +``` + +تغییرات کلیدی: +- `address`: از `IP_SERVER_KHAREJ` به `127.0.0.1` +- `port`: از `443` به `14000` (پورت VIO از مپینگ شما) + +**۴. مسیر ترافیک:** +``` +کاربر --> اینباند پنل ایران --> اوتباند پنل ایران (127.0.0.1:14000) + --> GFK client (پورت VIO) --> تونل QUIC روی TCP نقض‌شده + --> GFK server خارج --> 127.0.0.1:443 (اینباند پنل خارج) --> اینترنت +``` + +**چند پورت:** اگر پنل شما از چند پورت استفاده می‌کند، همه را مپ کنید: +``` +14000:443,14001:8080,14002:2020 +``` +سپس برای هر پورت (14000، 14001، 14002) اوتباند جداگانه در پنل ایران بسازید. + +> **توجه:** پیام وضعیت "Firewall: VIO port blocked" (که با رنگ سبز نمایش داده می‌شود) **عادی و صحیح** است. این به معنای آن است که فایروال به درستی برای کار raw socket در GFK تنظیم شده است. + +
+ +--- + ## شروع سریع ### ۱. راه‌اندازی سرور (VPS لینوکس) diff --git a/paqctl.sh b/paqctl.sh index cda574e..ef36869 100644 --- a/paqctl.sh +++ b/paqctl.sh @@ -1460,9 +1460,37 @@ setup_xray_for_gfk() { local target_port target_port=$(echo "${GFK_PORT_MAPPINGS:-14000:443}" | cut -d: -f2 | cut -d, -f1) - # If xray is already running (e.g. user has a panel), don't touch it + # If xray is already running (e.g. user has a panel), skip SOCKS5 setup. + # GFK is a raw TCP forwarder — traffic goes to whatever is on the target port. + # The user's panel/services handle the actual proxying. if pgrep -x xray &>/dev/null; then - log_info "Xray is already running — skipping install/config to preserve existing setup" + XRAY_PANEL_DETECTED=true + log_info "Existing Xray detected — skipping SOCKS5 setup (panel will handle traffic)" + + # Clean up any leftover standalone GFK xray from prior installs + pkill -f "xray run -c.*gfk-socks.json" 2>/dev/null || true + rm -f "${XRAY_CONFIG_DIR}/gfk-socks.json" 2>/dev/null + + # Check all target ports from mappings + local mapping pairs + IFS=',' read -ra pairs <<< "${GFK_PORT_MAPPINGS:-14000:443}" + for mapping in "${pairs[@]}"; do + local vio_port="${mapping%%:*}" + local tp="${mapping##*:}" + if ss -tln 2>/dev/null | grep -q ":${tp} "; then + log_success "Port $tp is listening — GFK will forward VIO port $vio_port to this port" + else + log_warn "Port $tp is NOT listening on this server — make sure your xray panel inbound is configured on port $tp" + fi + done + + echo "" + log_warn "ACTION REQUIRED: On your Iran server, configure the panel outbound:" + log_warn " → Set address to: 127.0.0.1" + local first_vio + first_vio=$(echo "${GFK_PORT_MAPPINGS:-14000:443}" | cut -d: -f1 | cut -d, -f1) + log_warn " → Set port to: ${first_vio} (VIO port, NOT the original server port)" + log_warn " See README for detailed panel configuration guide" return 0 fi @@ -1750,6 +1778,7 @@ if [ "\$ROLE" = "server" ]; then if command -v xray &>/dev/null || [ -x /usr/local/bin/xray ]; then if ! pgrep -f "xray run" &>/dev/null; then systemctl start xray 2>/dev/null || xray run -c /usr/local/etc/xray/config.json &>/dev/null & + sleep 2 fi fi cd "\$GFK_DIR" @@ -2853,6 +2882,7 @@ start_gfk_backend() { if command -v xray &>/dev/null || [ -x /usr/local/bin/xray ]; then if ! pgrep -f "xray run" &>/dev/null; then systemctl start xray 2>/dev/null || xray run -c /usr/local/etc/xray/config.json &>/dev/null & + sleep 2 fi fi # Run from GFK_DIR so relative script paths work @@ -5722,7 +5752,29 @@ setup_xray_for_gfk() { local target_port target_port=$(echo "${GFK_PORT_MAPPINGS:-14000:443}" | cut -d: -f2 | cut -d, -f1) if pgrep -x xray &>/dev/null; then - log_info "Xray is already running — skipping install/config to preserve existing setup" + XRAY_PANEL_DETECTED=true + log_info "Existing Xray detected — skipping SOCKS5 setup (panel will handle traffic)" + pkill -f "xray run -c.*gfk-socks.json" 2>/dev/null || true + rm -f "${XRAY_CONFIG_DIR}/gfk-socks.json" 2>/dev/null + # Check all target ports from mappings + local mapping pairs + IFS=',' read -ra pairs <<< "${GFK_PORT_MAPPINGS:-14000:443}" + for mapping in "${pairs[@]}"; do + local vio_port="${mapping%%:*}" + local tp="${mapping##*:}" + if ss -tln 2>/dev/null | grep -q ":${tp} "; then + log_success "Port $tp is listening — GFK will forward VIO port $vio_port to this port" + else + log_warn "Port $tp is NOT listening on this server — make sure your xray panel inbound is configured on port $tp" + fi + done + echo "" + log_warn "ACTION REQUIRED: On your Iran server, configure the panel outbound:" + log_warn " → Set address to: 127.0.0.1" + local first_vio + first_vio=$(echo "${GFK_PORT_MAPPINGS:-14000:443}" | cut -d: -f1 | cut -d, -f1) + log_warn " → Set port to: ${first_vio} (VIO port, NOT the original server port)" + log_warn " See README for detailed panel configuration guide" return 0 fi install_xray || return 1 @@ -5764,11 +5816,15 @@ _install_gfk_components() { # Generate TLS certificates for QUIC generate_gfk_certs || return 1 + # Setup Xray (server only — skipped if panel detected) + if [ "$ROLE" = "server" ]; then + setup_xray_for_gfk || return 1 + fi + # Generate parameters.py config generate_gfk_config || return 1 - # Setup Xray (install, configure, start) - setup_xray_for_gfk || return 1 + save_settings log_success "GFK components installed" } @@ -5803,6 +5859,26 @@ uninstall_paqctl() { stop_paqet stop_telegram_service + # Stop standalone GFK xray and clean up config + pkill -f "xray run -c.*gfk-socks.json" 2>/dev/null || true + rm -f /usr/local/etc/xray/gfk-socks.json 2>/dev/null + # Remove gfk-socks inbound from panel's xray config if present + if [ -f "$XRAY_CONFIG_FILE" ] && command -v python3 &>/dev/null; then + python3 -c " +import json, sys +try: + with open(sys.argv[1], 'r') as f: + cfg = json.load(f) + orig_len = len(cfg.get('inbounds', [])) + cfg['inbounds'] = [i for i in cfg.get('inbounds', []) if i.get('tag') != 'gfk-socks'] + if len(cfg['inbounds']) < orig_len: + with open(sys.argv[1], 'w') as f: + json.dump(cfg, f, indent=2) +except: pass +" "$XRAY_CONFIG_FILE" 2>/dev/null + systemctl restart xray 2>/dev/null || true + fi + # Remove ALL paqctl firewall rules (tagged with "paqctl" comment) log_info "Removing firewall rules..." _remove_all_paqctl_firewall_rules @@ -6696,7 +6772,7 @@ main() { download_gfk || { log_error "Failed to download GFK"; exit 1; } generate_gfk_certs || { log_error "Failed to generate certificates"; exit 1; } if [ "$ROLE" = "server" ]; then - # Install Xray to provide SOCKS5 proxy on the target port + # Install Xray to provide SOCKS5 proxy on the target port (skipped if panel detected) setup_xray_for_gfk || { log_error "Failed to setup Xray"; exit 1; } elif [ "$ROLE" = "client" ]; then install_microsocks || { log_error "Failed to install microsocks"; exit 1; } @@ -6790,9 +6866,18 @@ main() { _xray_port=$(echo "${GFK_PORT_MAPPINGS:-14000:443}" | cut -d: -f2 | cut -d, -f1) echo -e " VIO port: ${BOLD}${GFK_VIO_PORT}${NC}" echo -e " QUIC port: ${BOLD}${GFK_QUIC_PORT}${NC}" - echo -e " Xray: ${BOLD}127.0.0.1:${_xray_port} (SOCKS5)${NC}" - echo "" - echo -e " ${GREEN}✓ Xray SOCKS5 proxy installed and running${NC}" + if [ "${XRAY_PANEL_DETECTED:-false}" = "true" ]; then + echo -e " Xray: ${BOLD}Existing panel detected (forwarding to port ${_xray_port})${NC}" + echo "" + echo -e " ${GREEN}✓ GFK will forward traffic to your existing panel${NC}" + local _first_vio + _first_vio=$(echo "${GFK_PORT_MAPPINGS:-14000:443}" | cut -d: -f1 | cut -d, -f1) + echo -e " ${YELLOW}! ACTION: Configure Iran panel outbound → 127.0.0.1:${_first_vio}${NC}" + else + echo -e " Xray: ${BOLD}127.0.0.1:${_xray_port} (SOCKS5)${NC}" + echo "" + echo -e " ${GREEN}✓ Xray SOCKS5 proxy installed and running${NC}" + fi echo "" echo -e "${YELLOW}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e "${YELLOW}║ ${BOLD}CLIENT CONNECTION INFO - SAVE THIS!${NC}${YELLOW} ║${NC}"