diff --git a/.env.example b/.env.example index bb9cc63..b4ce045 100644 --- a/.env.example +++ b/.env.example @@ -36,6 +36,11 @@ ENABLE_TROJAN=true ENABLE_HYSTERIA2=true ENABLE_WIREGUARD=true ENABLE_DNSTT=true +ENABLE_PAQET=false +# Paqet advanced settings (optional) +# PAQET_LOG_LEVEL=info # Log level: debug, info, warn, error +# PAQET_KCP_MODE=fast # KCP mode: fast, normal, fast2, fast3 +# PAQET_ENCRYPTION=aes # Encryption: aes, tea, xor, none ENABLE_ADMIN_UI=true # ============================================================================= @@ -84,6 +89,7 @@ PORT_TROJAN=8443 # Trojan fallback PORT_WIREGUARD=51820 # WireGuard (UDP) PORT_WSTUNNEL=8080 # WebSocket tunnel for WireGuard PORT_DNS=53 # DNS tunnel (dnstt) +PORT_PAQET=9999 # Paqet raw packet proxy PORT_ADMIN=9443 # Admin dashboard # ============================================================================= diff --git a/CHANGELOG.md b/CHANGELOG.md index 327caa9..a4645fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `moav test` verbose flag (`-v` or `--verbose`) for debugging connection issues +- **Paqet protocol support** - Raw packet-level proxy that bypasses OS TCP/IP stack + - New `--profile paqet` for starting paqet service + - Auto-detection of network interface, server IP, and gateway MAC + - Automatic iptables NOTRACK rules to prevent kernel RST packets + - Client config generation in user bundles (`paqet-client.yaml`, `paqet-instructions.txt`) + - VPS compatibility check (OpenVZ/LXC not supported - requires KVM or bare metal) + - Documentation for setup, troubleshooting, and iptables persistence ### Changed - `moav test` now prefers IPv4 configs over IPv6 (tests `reality.txt` before `reality-ipv6.txt`) - `moav test` treats IPv6 network failures as warnings instead of errors (IPv6 may not be available in container) +- Client container now includes paqet binary and libpcap for raw packet proxy support ### Fixed - **WireGuard-wstunnel not forwarding traffic** - wstunnel was trying to forward to localhost instead of wireguard container (changed `127.0.0.1:51820` to `moav-wireguard:51820`) diff --git a/Dockerfile.client b/Dockerfile.client index 5ddf8ec..38625a3 100644 --- a/Dockerfile.client +++ b/Dockerfile.client @@ -35,6 +35,14 @@ RUN go install gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/sn echo "snowflake build failed" RUN cp /go/bin/client /snowflake-client 2>/dev/null || touch /snowflake-client +# Build paqet from source +FROM golang:1.23-alpine AS paqet-builder +RUN apk add --no-cache git libpcap-dev gcc musl-dev +ENV GOTOOLCHAIN=auto +RUN git clone --depth 1 https://github.com/hanselime/paqet.git /src/paqet && \ + cd /src/paqet && \ + go build -o /paqet ./cmd || touch /paqet + # ============================================================================= # Final image - prefer pre-built binaries, fallback to built versions # ============================================================================= @@ -60,12 +68,14 @@ RUN apk add --no-cache \ iproute2 \ bind-tools \ tor \ + libpcap \ && rm -rf /var/cache/apk/* # Copy built binaries from builder stages (as fallback) COPY --from=singbox-builder /sing-box /tmp/sing-box-built COPY --from=dnstt-builder /dnstt-client /tmp/dnstt-client-built COPY --from=snowflake-builder /snowflake-client /tmp/snowflake-client-built +COPY --from=paqet-builder /paqet /tmp/paqet-built # sing-box: try pre-built, fallback to built # TARGETARCH is amd64 or arm64 @@ -103,6 +113,13 @@ RUN cp /tmp/dnstt-client-built /usr/local/bin/dnstt-client && \ echo "dnstt: build failed (optional)" RUN rm -f /tmp/dnstt-client-built +# paqet: always use built (no official releases) +RUN cp /tmp/paqet-built /usr/local/bin/paqet && \ + chmod +x /usr/local/bin/paqet && \ + echo "paqet: using locally built binary" || \ + echo "paqet: build failed (optional)" +RUN rm -f /tmp/paqet-built + # Create directories RUN mkdir -p /config /app /state /var/log/moav diff --git a/Dockerfile.paqet b/Dockerfile.paqet new file mode 100644 index 0000000..d3f0689 --- /dev/null +++ b/Dockerfile.paqet @@ -0,0 +1,56 @@ +# ============================================================================= +# MoaV Paqet - Raw Packet Level Proxy +# ============================================================================= +# Paqet bypasses OS TCP/IP stack using pcap for packet capture/injection. +# Requires: --network host --privileged (or NET_RAW + NET_ADMIN capabilities) +# ============================================================================= + +FROM golang:1.23-alpine AS builder + +# Install build dependencies +RUN apk add --no-cache git libpcap-dev gcc musl-dev + +# Enable toolchain auto-download for newer Go versions +ENV GOTOOLCHAIN=auto + +# Clone paqet source +ARG PAQET_VERSION=master +RUN git clone --depth 1 --branch ${PAQET_VERSION} https://github.com/hanselime/paqet.git /src/paqet + +WORKDIR /src/paqet + +# Download dependencies first (better caching) +RUN go mod download + +# Build paqet +RUN CGO_ENABLED=1 go build -ldflags="-s -w" -o /paqet ./cmd + +# ============================================================================= +# Final image +# ============================================================================= +FROM alpine:3.20 + +# Install runtime dependencies +RUN apk add --no-cache \ + libpcap \ + iptables \ + iproute2 \ + bash \ + curl \ + jq \ + && rm -rf /var/cache/apk/* + +# Copy paqet binary +COPY --from=builder /paqet /usr/local/bin/paqet +RUN chmod +x /usr/local/bin/paqet + +# Copy entrypoint +COPY scripts/paqet-entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + +# Create directories +RUN mkdir -p /etc/paqet /state + +WORKDIR /app + +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/README-fa.md b/README-fa.md index 66d0168..7a4e5cf 100644 --- a/README-fa.md +++ b/README-fa.md @@ -8,7 +8,7 @@ ## ویژگی‌ها -- **پروتکل‌های متعدد** - Reality (VLESS)، Trojan، Hysteria2، WireGuard (مستقیم و wstunnel)، تونل DNS +- **پروتکل‌های متعدد** - Reality (VLESS)، Trojan، Hysteria2، WireGuard (مستقیم و wstunnel)، Paqet، تونل DNS - **اولویت پنهان‌کاری** - تمام ترافیک شبیه HTTPS معمولی، WebSocket، یا DNS به نظر می‌رسد - **اعتبارنامه‌های جداگانه برای هر کاربر** - ایجاد، لغو و مدیریت کاربران به صورت مستقل - **نصب آسان** - مبتنی بر Docker Compose، راه‌اندازی با یک دستور @@ -142,6 +142,7 @@ docker compose --profile all up -d # شروع تمام سروی | Trojan | 8443/tcp | ★★★★☆ | ★★★★☆ | پشتیبان، از دامنه شما استفاده می‌کند | | WireGuard (مستقیم) | 51820/udp | ★★★☆☆ | ★★★★★ | VPN کامل، نصب ساده | | WireGuard (wstunnel) | 8080/tcp | ★★★★☆ | ★★★★☆ | VPN وقتی UDP مسدود است | +| Paqet | 9999/tcp | ★★★☆☆ | ★★★☆☆ | بسته خام، دور زدن فایروال OS | | تونل DNS | 53/udp | ★★★☆☆ | ★☆☆☆☆ | آخرین راه‌حل، سخت برای مسدود کردن | | Psiphon | - | ★★★★☆ | ★★★☆☆ | مستقل، نیازی به سرور ندارد | | Tor (Snowflake) | - | ★★★★☆ | ★★☆☆☆ | مستقل، از شبکه Tor استفاده می‌کند | diff --git a/README.md b/README.md index 567cb9d..5fb596a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Multi-protocol censorship circumvention stack optimized for hostile network envi ## Features -- **Multiple protocols** - Reality (VLESS), Trojan, Hysteria2, WireGuard (direct & wstunnel), DNS tunnel +- **Multiple protocols** - Reality (VLESS), Trojan, Hysteria2, WireGuard (direct & wstunnel), Paqet, DNS tunnel - **Stealth-first** - All traffic looks like normal HTTPS, WebSocket, or DNS - **Per-user credentials** - Create, revoke, and manage users independently - **Easy deployment** - Docker Compose based, single command setup @@ -120,6 +120,7 @@ See [docs/SETUP.md](docs/SETUP.md) for complete setup instructions. | Trojan | 8443/tcp | ★★★★☆ | ★★★★☆ | Backup, uses your domain | | WireGuard (Direct) | 51820/udp | ★★★☆☆ | ★★★★★ | Full VPN, simple setup | | WireGuard (wstunnel) | 8080/tcp | ★★★★☆ | ★★★★☆ | VPN when UDP is blocked | +| Paqet | 9999/tcp | ★★★☆☆ | ★★★☆☆ | Raw packet, bypasses OS firewall | | DNS Tunnel | 53/udp | ★★★☆☆ | ★☆☆☆☆ | Last resort, hard to block | | Psiphon | - | ★★★★☆ | ★★★☆☆ | Standalone, no server needed | | Tor (Snowflake) | - | ★★★★☆ | ★★☆☆☆ | Standalone, uses Tor network | diff --git a/configs/paqet/.gitkeep b/configs/paqet/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml index a8a40b6..3db0e37 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -132,6 +132,31 @@ services: - dnstt - all + # =========================================================================== + # PAQET: Raw packet-level proxy (last resort, bypasses OS firewall) + # =========================================================================== + paqet: + build: + context: . + dockerfile: Dockerfile.paqet + container_name: moav-paqet + restart: unless-stopped + # REQUIRED: Host network mode for raw packet access + network_mode: host + # REQUIRED: Privileged mode for pcap/raw sockets + privileged: true + volumes: + - moav_state:/state + - ./configs/paqet:/etc/paqet + environment: + - TZ=${TZ:-UTC} + - PAQET_PORT=${PORT_PAQET:-9999} + - PAQET_LOG_LEVEL=${PAQET_LOG_LEVEL:-info} + - PAQET_KCP_MODE=${PAQET_KCP_MODE:-fast} + - PAQET_ENCRYPTION=${PAQET_ENCRYPTION:-aes} + profiles: + - paqet + # =========================================================================== # CERTBOT: TLS certificate management # =========================================================================== @@ -290,7 +315,9 @@ services: - ENABLE_HYSTERIA2=${ENABLE_HYSTERIA2:-true} - ENABLE_WIREGUARD=${ENABLE_WIREGUARD:-true} - ENABLE_DNSTT=${ENABLE_DNSTT:-true} + - ENABLE_PAQET=${ENABLE_PAQET:-false} - ENABLE_ADMIN_UI=${ENABLE_ADMIN_UI:-true} + - PORT_PAQET=${PORT_PAQET:-9999} profiles: - setup diff --git a/docs/CLIENTS.md b/docs/CLIENTS.md index 2b59d34..dce7e9e 100644 --- a/docs/CLIENTS.md +++ b/docs/CLIENTS.md @@ -17,6 +17,7 @@ This guide explains how to connect to MoaV from various devices. - [WireGuard Setup](#wireguard-setup) - [Hysteria2 Setup](#hysteria2-setup) - [DNS Tunnel Setup (Last Resort)](#dns-tunnel-setup-last-resort) +- [Paqet Setup (Last Resort)](#paqet-setup-last-resort) - [Psiphon Setup](#psiphon-setup) - [About Psiphon Conduit (Server Feature)](#about-psiphon-conduit-server-feature) - [About Tor Snowflake (Server Feature)](#about-tor-snowflake-server-feature) @@ -37,6 +38,7 @@ This guide explains how to connect to MoaV from various devices. | [WireGuard](https://www.wireguard.com/) (Direct) | 51820/udp | Full VPN mode, simple setup | | [WireGuard](https://www.wireguard.com/) + [wstunnel](https://github.com/erebe/wstunnel) | 8080/tcp | VPN wrapped in WebSocket | | [DNS Tunnel](https://www.bamsoftware.com/software/dnstt/) | 53/udp | Last resort, slow but hard to block | +| [Paqet](https://github.com/hanselime/paqet) | 9999/tcp | Raw packet proxy, bypasses OS firewall | | [Psiphon](https://psiphon.ca/) | Various | Standalone app, uses Psiphon network | | [Tor](https://www.torproject.org/) (Snowflake) | Various | Uses Tor network | @@ -130,7 +132,8 @@ Try these in order. If one doesn't work, try the next: 5. **WireGuard (wstunnel)** - VPN wrapped in WebSocket, for restrictive networks (port 8080/tcp) 6. **Tor (Snowflake)** - Uses Tor network (no server needed) 7. **DNS Tunnel** - Last resort, very slow but hard to block (port 53/udp) -8. **Psiphon** - Standalone app only, uses Psiphon network (not via MoaV client) +8. **Paqet** - Raw packet proxy, bypasses OS firewall (port 9999/tcp, requires root) +9. **Psiphon** - Standalone app only, uses Psiphon network (not via MoaV client) --- @@ -154,7 +157,7 @@ moav test user1 moav test user1 --json ``` -The test checks: Reality, Trojan, Hysteria2, WireGuard (config validation), and dnstt. +The test checks: Reality, Trojan, Hysteria2, WireGuard (config validation), dnstt, and Paqet. **Sample output:** ``` @@ -227,6 +230,7 @@ The client container includes: - **wireguard-go** - Userspace WireGuard implementation - **wstunnel** - WebSocket tunnel for WireGuard - **dnstt-client** - DNS tunnel client +- **paqet** - Raw packet proxy (requires privileged mode) - **snowflake-client** - Tor Snowflake pluggable transport - **tor** - Tor daemon @@ -505,6 +509,106 @@ See `dnstt-instructions.txt` in your bundle for detailed steps. --- +## Paqet Setup (Last Resort) + +Paqet is a raw packet-level proxy that bypasses the OS TCP/IP stack using pcap. Use this when: +- Other protocols are actively blocked +- Deep packet inspection is defeating standard protocols +- You need to operate below the firewall layer + +**Requirements:** +- Root/administrator privileges +- libpcap installed +- NOT OpenVZ/LXC container (requires KVM, Xen, or bare metal) + +### Installation + +**Linux:** +```bash +# Install libpcap +sudo apt install libpcap-dev # Debian/Ubuntu +sudo dnf install libpcap-devel # Fedora/RHEL + +# Download paqet +# From: https://github.com/hanselime/paqet/releases +# Or build from source: +go install github.com/hanselime/paqet/cmd/paqet@latest +``` + +**macOS:** +```bash +# libpcap is pre-installed +# Download paqet binary or build from source +``` + +**Windows:** +1. Install [Npcap](https://npcap.com) (required for raw packet access) +2. Download paqet.exe from releases + +### Configuration + +Your bundle contains `paqet-client.yaml` and `paqet-instructions.txt`. + +**You must fill in YOUR network details:** + +1. Find your network interface: + ```bash + # Linux + ip a + # macOS + ifconfig + # Windows + Get-NetAdapter + ``` + +2. Find your local IP: + ```bash + # Linux + ip -4 addr show eth0 | grep inet + # macOS + ifconfig en0 | grep inet + ``` + +3. Find your gateway/router MAC: + ```bash + # Find gateway IP + ip route | grep default # Linux + netstat -rn | grep default # macOS + + # Get MAC for gateway IP + arp -n GATEWAY_IP + ``` + +4. Edit `paqet-client.yaml`: + ```yaml + network: + interface: "eth0" # Your interface + ipv4: + addr: "192.168.1.100:0" # Your local IP + router_mac: "aa:bb:cc:dd:ee:ff" # Your gateway MAC + ``` + +### Running + +```bash +# Linux/macOS (requires root) +sudo paqet run -c paqet-client.yaml + +# Windows (run as Administrator) +paqet.exe run -c paqet-client.yaml +``` + +This creates a SOCKS5 proxy at `127.0.0.1:1080`. + +### Troubleshooting + +- **"permission denied"** - Run as root/admin +- **"no route to host"** - Check gateway MAC address +- **"pcap error"** - Install libpcap, verify interface name +- **OpenVZ/LXC error** - Paqet requires KVM or bare metal (raw sockets not supported in containers) + +--- + ## Psiphon Setup Psiphon is a standalone circumvention tool that doesn't require your own server. It connects to the Psiphon network - a large, distributed system designed for censorship circumvention. diff --git a/docs/SETUP.md b/docs/SETUP.md index 41e53ac..1c7c857 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -360,6 +360,7 @@ docker compose --profile proxy --profile conduit up -d # Proxy + Psiphon # proxy - sing-box + decoy (main proxy services) # wireguard - WireGuard VPN via wstunnel # dnstt - DNS tunnel (last resort) +# paqet - Paqet raw packet proxy (last resort, requires host network) # admin - Stats dashboard (https://domain:9443 or https://ip:9443 in domain-less mode) # conduit - Psiphon bandwidth donation (includes traffic stats by country) # snowflake - Tor Snowflake proxy (bandwidth donation for Tor users) diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index aed078d..2eec3cb 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -251,6 +251,86 @@ docker compose logs sing-box | grep -i hysteria nc -vuz YOUR_SERVER_IP 443 ``` +### Paqet not starting + +Paqet requires special system capabilities. Common issues: + +1. **OpenVZ/LXC container detected:** + ``` + OpenVZ detected - raw sockets not supported! + ``` + **Solution:** Paqet requires KVM, Xen, or bare metal. OpenVZ/LXC don't support raw sockets. + +2. **Missing libpcap:** + ``` + error loading libpcap + ``` + **Solution:** + ```bash + # Debian/Ubuntu + apt install libpcap-dev + + # Alpine (in container) + apk add libpcap + ``` + +3. **Permission denied:** + ``` + permission denied creating raw socket + ``` + **Solution:** Paqet must run with root/admin privileges and the container needs: + - `--network host` + - `--privileged` (or `--cap-add NET_RAW --cap-add NET_ADMIN`) + +4. **Gateway MAC not detected:** + ``` + Could not detect gateway MAC address + ``` + **Solution:** The entrypoint script auto-detects network config. If it fails: + ```bash + # Check gateway IP + ip route | grep default + + # Ping gateway to populate ARP table + ping -c 1 GATEWAY_IP + + # Get MAC + ip neigh show GATEWAY_IP + ``` + +5. **iptables rules not set:** + Paqet needs specific iptables rules to prevent kernel RST packets: + ```bash + # These should be set automatically by the entrypoint + iptables -t raw -A PREROUTING -p tcp --dport 9999 -j NOTRACK + iptables -t raw -A OUTPUT -p tcp --sport 9999 -j NOTRACK + iptables -t mangle -A OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP + ``` + +### Paqet iptables rules not persisting + +The iptables rules set by paqet's entrypoint are lost on reboot. To persist them: + +**Debian/Ubuntu:** +```bash +# Save rules +iptables-save > /etc/iptables/rules.v4 + +# Install iptables-persistent +apt install iptables-persistent +``` + +**Alpine:** +```bash +# Save rules +/etc/init.d/iptables save + +# Enable at boot +rc-update add iptables +``` + +Or add the rules to your server's startup script. + ### WireGuard connected but no traffic **Check if peer is loaded:** diff --git a/moav.sh b/moav.sh index d42ee9c..8814ce7 100755 --- a/moav.sh +++ b/moav.sh @@ -1927,8 +1927,8 @@ show_usage() { echo " regenerate-users Regenerate all user bundles with current .env" echo " setup-dns Free port 53 for dnstt (disables systemd-resolved)" echo "" - echo "Profiles: proxy, wireguard, dnstt, admin, conduit, snowflake, client, all" - echo "Services: sing-box, decoy, wstunnel, wireguard, dnstt, admin, psiphon-conduit, snowflake" + echo "Profiles: proxy, wireguard, dnstt, admin, conduit, snowflake, paqet, client, all" + echo "Services: sing-box, decoy, wstunnel, wireguard, dnstt, admin, psiphon-conduit, snowflake, paqet" echo "Aliases: conduit→psiphon-conduit, singbox→sing-box, wg→wireguard, dns→dnstt" echo "" echo "Examples:" @@ -2129,7 +2129,7 @@ cmd_profiles() { cmd_start() { local profiles="" - local valid_profiles="proxy wireguard dnstt admin conduit snowflake client all setup" + local valid_profiles="proxy wireguard dnstt admin conduit snowflake paqet client all setup" if [[ $# -eq 0 ]]; then # No arguments - check for DEFAULT_PROFILES in .env @@ -2506,7 +2506,7 @@ cmd_client() { if [[ -z "$user" ]]; then error "Usage: moav client connect USERNAME [--protocol PROTOCOL]" echo "" - echo "Protocols: auto, reality, trojan, hysteria2, wireguard, psiphon, tor, dnstt" + echo "Protocols: auto, reality, trojan, hysteria2, wireguard, psiphon, tor, dnstt, paqet" echo "" echo "Available users:" ls -1 outputs/bundles/ 2>/dev/null || echo " No users found" diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 51eb4ce..9aca45a 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -172,6 +172,25 @@ else REALITY_TARGET_PORT="" fi +# ----------------------------------------------------------------------------- +# Generate Paqet encryption key (if enabled) +# ----------------------------------------------------------------------------- +if [[ "${ENABLE_PAQET:-false}" == "true" ]]; then + if [[ ! -f "$STATE_DIR/keys/paqet.key" ]]; then + log_info "Generating Paqet encryption key..." + # Generate a strong random key (32 chars, alphanumeric + special) + PAQET_KEY=$(pwgen -s 32 1) + echo "$PAQET_KEY" > "$STATE_DIR/keys/paqet.key" + chmod 600 "$STATE_DIR/keys/paqet.key" + else + PAQET_KEY=$(cat "$STATE_DIR/keys/paqet.key") + log_info "Using existing Paqet encryption key" + fi + export PAQET_KEY +else + PAQET_KEY="" +fi + # ----------------------------------------------------------------------------- # Export variables needed by generate-user.sh # ----------------------------------------------------------------------------- @@ -186,6 +205,8 @@ export ENABLE_TROJAN="${ENABLE_TROJAN:-true}" export ENABLE_HYSTERIA2="${ENABLE_HYSTERIA2:-true}" export ENABLE_WIREGUARD="${ENABLE_WIREGUARD:-true}" export ENABLE_DNSTT="${ENABLE_DNSTT:-true}" +export ENABLE_PAQET="${ENABLE_PAQET:-false}" +export PORT_PAQET="${PORT_PAQET:-9999}" # ----------------------------------------------------------------------------- # Generate WireGuard server config (before creating users) diff --git a/scripts/client-connect.sh b/scripts/client-connect.sh index 48d8302..a51a4c6 100644 --- a/scripts/client-connect.sh +++ b/scripts/client-connect.sh @@ -24,6 +24,7 @@ TEST_TIMEOUT="${TEST_TIMEOUT:-10}" # Protocol priority for auto mode # Note: psiphon excluded - requires embedded server list, not supported in client mode +# Note: paqet excluded from auto - requires privileged mode and network config PROTOCOL_PRIORITY=(reality hysteria2 trojan wireguard tor dnstt) # State @@ -397,6 +398,64 @@ connect_dnstt() { return 0 } +# Connect using paqet (raw packet proxy) +# NOTE: Requires privileged mode and host networking - normally run via moav client +connect_paqet() { + local config_file="" + + for f in "$CONFIG_DIR"/paqet*.yaml "$CONFIG_DIR"/paqet*.yml; do + [[ -f "$f" ]] && config_file="$f" && break + done + + if [[ -z "$config_file" ]]; then + log_error "No paqet config found" + return 1 + fi + + # Check if config needs customization + if grep -q "CHANGE_ME" "$config_file"; then + log_error "Paqet config needs customization first" + log_info "Edit $config_file and fill in your network details:" + log_info " - interface: your network interface (eth0, en0, etc.)" + log_info " - addr: your local IP address" + log_info " - router_mac: your gateway's MAC address" + log_info "See paqet-instructions.txt for help finding these values" + return 1 + fi + + # Check if paqet binary exists + if ! command -v paqet >/dev/null 2>&1; then + log_error "paqet binary not found" + log_info "Download from: https://github.com/hanselime/paqet/releases" + return 1 + fi + + # Extract server for logging + local server=$(grep -E "^\s*addr:" "$config_file" | grep -v "YOUR_LOCAL" | sed 's/.*addr:[[:space:]]*//' | tr -d '"' | head -1) + + log_info "Starting paqet client to $server..." + log_warn "Note: paqet requires root/admin privileges and raw socket access" + + paqet run -c "$config_file" & + CURRENT_PID=$! + CURRENT_PROTOCOL="paqet" + + sleep 3 + + if ! kill -0 $CURRENT_PID 2>/dev/null; then + log_error "paqet failed to start" + log_info "Common issues:" + log_info " - Not running as root/admin" + log_info " - OpenVZ/LXC container (needs KVM or bare metal)" + log_info " - libpcap not installed" + log_info " - Incorrect network interface or gateway MAC" + return 1 + fi + + log_success "paqet tunnel established" + return 0 +} + # Connect using Psiphon (standalone, doesn't need MoaV server) # NOTE: Not implemented - Psiphon tunnel-core requires embedded server lists # that are not publicly available. Use the official Psiphon apps instead: @@ -550,6 +609,9 @@ main() { dnstt) connect_dnstt && connected=true ;; + paqet) + connect_paqet && connected=true + ;; *) log_error "Unknown protocol: $PROTOCOL" exit 1 diff --git a/scripts/client-test.sh b/scripts/client-test.sh index 800ae45..4274d1b 100644 --- a/scripts/client-test.sh +++ b/scripts/client-test.sh @@ -759,6 +759,64 @@ test_dnstt() { fi } +# Test paqet (raw packet proxy - config validation only) +test_paqet() { + log_info "Testing paqet (config validation)..." + + local config_file="" + local detail="" + + for f in "$CONFIG_DIR"/paqet*.yaml "$CONFIG_DIR"/paqet*.yml; do + [[ -f "$f" ]] && config_file="$f" && break + done + + if [[ -z "$config_file" ]]; then + detail="No paqet config found in bundle" + log_warn "$detail" + RESULTS[paqet]="skip" + DETAILS[paqet]="$detail" + return + fi + + log_debug "Using config: $config_file" + + # Extract server address + local server=$(grep -E "^\s*addr:" "$config_file" | grep -v "YOUR_LOCAL" | sed 's/.*addr:[[:space:]]*//' | tr -d '"' | head -1) + local key=$(grep -E "^\s*key:" "$config_file" | sed 's/.*key:[[:space:]]*//' | tr -d '"' | head -1) + + log_debug "Parsed: server=$server key=${key:0:10}..." + + if [[ -z "$server" ]] || [[ -z "$key" ]]; then + detail="Could not parse paqet config (missing server or key)" + log_error "$detail" + RESULTS[paqet]="fail" + DETAILS[paqet]="$detail" + return + fi + + # Check if config needs user customization + if grep -q "CHANGE_ME" "$config_file"; then + log_warn "Paqet config needs customization (network details required)" + RESULTS[paqet]="warn" + DETAILS[paqet]="Config valid, but needs network details (interface, router_mac)" + return + fi + + # Validate paqet binary exists + if ! command -v paqet >/dev/null 2>&1; then + log_warn "paqet binary not available" + RESULTS[paqet]="warn" + DETAILS[paqet]="Config found, but paqet client not installed" + return + fi + + # Note: We can't fully test paqet without raw socket access + # which requires host network mode and privileges + log_success "Paqet config valid, server: $server" + RESULTS[paqet]="warn" + DETAILS[paqet]="Config valid for $server (requires privileged mode to test)" +} + # ============================================================================= # Output Functions # ============================================================================= @@ -794,7 +852,7 @@ output_json() { EOF local first=true - for protocol in reality trojan hysteria2 wireguard dnstt; do + for protocol in reality trojan hysteria2 wireguard dnstt paqet; do if [[ -n "${RESULTS[$protocol]:-}" ]]; then [[ "$first" != "true" ]] && echo "," first=false @@ -825,7 +883,7 @@ output_human() { echo "" echo "───────────────────────────────────────────────────────────────" - for protocol in reality trojan hysteria2 wireguard dnstt; do + for protocol in reality trojan hysteria2 wireguard dnstt paqet; do if [[ -n "${RESULTS[$protocol]:-}" ]]; then local status="${RESULTS[$protocol]}" local detail="${DETAILS[$protocol]:-}" @@ -864,6 +922,7 @@ main() { test_hysteria2 test_wireguard test_dnstt + test_paqet # Output results if [[ "${JSON_OUTPUT:-false}" == "true" ]]; then diff --git a/scripts/generate-user.sh b/scripts/generate-user.sh index 41f97a6..502682e 100755 --- a/scripts/generate-user.sh +++ b/scripts/generate-user.sh @@ -232,6 +232,127 @@ if [[ "${ENABLE_DNSTT:-true}" == "true" ]]; then log_info " - dnstt instructions generated" fi +# ----------------------------------------------------------------------------- +# Generate Paqet client config (if enabled) +# ----------------------------------------------------------------------------- +if [[ "${ENABLE_PAQET:-false}" == "true" ]]; then + PAQET_KEY_FILE="/state/keys/paqet.key" + PAQET_PORT="${PORT_PAQET:-9999}" + + if [[ -f "$PAQET_KEY_FILE" ]]; then + PAQET_KEY=$(cat "$PAQET_KEY_FILE") + + # Generate client config template (user needs to fill in their network details) + cat > "$OUTPUT_DIR/paqet-client.yaml" < "$OUTPUT_DIR/paqet-instructions.txt" < | grep inet +# Gateway: ip route | grep default +# Gateway MAC: arp -n +# +# macOS: +# Interface: ifconfig (look for en0) +# Local IP: ifconfig | grep inet +# Gateway: netstat -rn | grep default +# Gateway MAC: arp -n +# +# Windows: +# Interface: Get-NetAdapter | Select-Object Name, InterfaceGuid +# Local IP: ipconfig +# Gateway: ipconfig | findstr Gateway +# Gateway MAC: arp -a + +# Step 4: Edit paqet-client.yaml +# ------------------------------ +# Replace CHANGE_ME values with your network details: +# - interface: your network interface name +# - addr: your local IP (keep :0 for auto port) +# - router_mac: your gateway's MAC address + +# Step 5: Run paqet +# ----------------- +# Linux/macOS: sudo paqet run -c paqet-client.yaml +# Windows: Run as Administrator: paqet run -c paqet-client.yaml + +# Step 6: Use the proxy +# --------------------- +# Configure applications to use SOCKS5 proxy at 127.0.0.1:1080 + +# Server Connection Info: +# ----------------------- +# Server: ${SERVER_IP}:${PAQET_PORT} +# Protocol: KCP over raw TCP packets +# Encryption: AES + +# Troubleshooting: +# ---------------- +# - "permission denied" → Run as root/admin +# - "no route to host" → Check firewall, gateway MAC +# - "pcap error" → Install libpcap, check interface name +# - OpenVZ/LXC error → Use KVM VPS or bare metal instead +EOF + + log_info " - Paqet config generated" + else + log_warn " - Paqet key not found, skipping config generation" + fi +fi + # ----------------------------------------------------------------------------- # Generate README.html from template # ----------------------------------------------------------------------------- diff --git a/scripts/paqet-entrypoint.sh b/scripts/paqet-entrypoint.sh new file mode 100644 index 0000000..ffbf720 --- /dev/null +++ b/scripts/paqet-entrypoint.sh @@ -0,0 +1,236 @@ +#!/bin/bash +# ============================================================================= +# Paqet Server Entrypoint +# Auto-detects network configuration and starts paqet server +# ============================================================================= + +# Note: We don't use pipefail here because commands like `cmd | head -1` +# cause SIGPIPE when head exits after reading one line, which pipefail +# treats as an error (exit code 141). +set -eu + +# Colors for logging +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { echo -e "${BLUE}[paqet]${NC} $1"; } +log_success() { echo -e "${GREEN}[paqet]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[paqet]${NC} $1"; } +log_error() { echo -e "${RED}[paqet]${NC} $1"; } + +# ============================================================================= +# VPS Compatibility Check +# ============================================================================= +check_vps_compatibility() { + log_info "Checking VPS compatibility..." + + # Check for OpenVZ (doesn't support raw sockets) + if [[ -f /proc/user_beancounters ]]; then + log_error "OpenVZ detected - raw sockets not supported!" + log_error "Paqet requires KVM, Xen, or bare metal servers." + exit 1 + fi + + # Check for LXC/container environment + if [[ -f /proc/1/environ ]] && grep -q "container=" /proc/1/environ 2>/dev/null; then + log_warn "Container environment detected - raw sockets may not work" + fi + + # Test raw socket capability + if ! capsh --print 2>/dev/null | grep -q "cap_net_raw"; then + # Try alternative check + if [[ ! -w /dev/net/tun ]] && [[ "$(id -u)" != "0" ]]; then + log_warn "May not have raw socket capabilities" + fi + fi + + log_success "VPS compatibility check passed" +} + +# ============================================================================= +# Network Auto-Detection +# ============================================================================= +detect_interface() { + # Find the default route interface + local iface=$(ip route | grep default | awk '{print $5}' | head -1) + + if [[ -z "$iface" ]]; then + # Fallback: find first non-lo interface with an IP + iface=$(ip -o -4 addr show | grep -v ' lo ' | awk '{print $2}' | head -1) + fi + + echo "$iface" +} + +detect_server_ip() { + local iface="$1" + ip -4 addr show "$iface" | awk '/inet / {print $2}' | cut -d/ -f1 | head -1 +} + +detect_gateway_ip() { + ip route | grep default | awk '{print $3}' | head -1 +} + +detect_gateway_mac() { + local gateway_ip="$1" + + # Ping gateway to ensure ARP entry exists + ping -c 1 -W 1 "$gateway_ip" >/dev/null 2>&1 || true + + # Get MAC from ARP table + local mac=$(ip neigh show "$gateway_ip" 2>/dev/null | awk '{print $5}' | head -1) + + # Fallback to arp command + if [[ -z "$mac" ]] || [[ "$mac" == "FAILED" ]]; then + mac=$(arp -n "$gateway_ip" 2>/dev/null | tail -1 | awk '{print $3}') + fi + + echo "$mac" +} + +# ============================================================================= +# iptables Setup +# ============================================================================= +setup_iptables() { + local port="$1" + + log_info "Setting up iptables rules for port $port..." + + # Check if rules already exist + if iptables -t raw -C PREROUTING -p tcp --dport "$port" -j NOTRACK 2>/dev/null; then + log_info "iptables rules already configured" + return 0 + fi + + # Bypass connection tracking (essential for paqet) + iptables -t raw -A PREROUTING -p tcp --dport "$port" -j NOTRACK || log_warn "Failed to add PREROUTING NOTRACK rule" + iptables -t raw -A OUTPUT -p tcp --sport "$port" -j NOTRACK || log_warn "Failed to add OUTPUT NOTRACK rule" + + # Prevent kernel from sending RST packets + iptables -t mangle -A OUTPUT -p tcp --sport "$port" --tcp-flags RST RST -j DROP || log_warn "Failed to add RST DROP rule" + + # Allow traffic on the port + iptables -t filter -A INPUT -p tcp --dport "$port" -j ACCEPT 2>/dev/null || true + iptables -t filter -A OUTPUT -p tcp --sport "$port" -j ACCEPT 2>/dev/null || true + + log_success "iptables rules configured" +} + +# ============================================================================= +# Configuration Generation +# ============================================================================= +generate_config() { + local config_file="$1" + local interface="$2" + local server_ip="$3" + local gateway_mac="$4" + local port="$5" + local key="$6" + + log_info "Generating paqet server configuration..." + + cat > "$config_file" <