paqctl Setup Guide: Bypass Censorship with Paqet and GFW-Knocker

15 min read
Intermediate Censorship Proxy paqctl Paqet GFW-Knocker KCP QUIC Privacy Guide

Prerequisites

  • A VPS with a public IP and root access
  • Windows, macOS, or Linux client machine
  • Npcap installed on Windows (the installer handles this)
  • Basic Linux command line knowledge

Quick Answer: paqctl is a unified tool for two censorship bypass methods. Paqet uses KCP over raw sockets with custom TCP flags. GFW-Knocker uses violated TCP packets + QUIC tunneling. Install the server: curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash. Then set up the client on Windows/Mac/Linux and connect through a local SOCKS5 proxy.

Need a VPS? Get started with Vultr (free credit for new accounts), DigitalOcean ($200 free credit), or RackNerd (cheap annual deals starting ~$10/year).

Note: paqctl is currently in alpha (v1.0.0-alpha). Expect breaking changes between releases.


What Is paqctl?

paqctl is a unified management tool for two different censorship bypass methods. You run the server on a VPS outside the restricted network and the client on your local machine. Both methods create a local SOCKS5 proxy that routes traffic through the tunnel.

The two methods:

Paqet GFW-Knocker (GFK)
Difficulty Easy Advanced
Best for Most situations Heavy censorship (GFW, deep throttling)
Local proxy 127.0.0.1:1080 127.0.0.1:14000
Technology KCP over raw sockets Violated TCP + QUIC tunnel
Server needs Just paqet GFK + Xray
Client type Binary (Go) Python scripts

How Paqet Works

Paqet sends traffic using the KCP protocol over raw TCP sockets with custom TCP flags.

Your Device                  Your VPS                    Internet
+--------------+            +--------------+           +----------+
|  Browser     |            |  Paqet       |           |  Google  |
|      |       |  KCP over  |  Server      |           |  YouTube |
|      v       |  raw TCP   |      |       |           |  etc.    |
|  Paqet       | ---------> |      v       | --------> |          |
|  Client      |  (custom   |  SOCKS5      |           |          |
| 127.0.0.1    |   flags)   |  forward     |           |          |
|   :1080      |            |              |           |          |
+--------------+            +--------------+           +----------+

Why DPI cannot detect it:

  1. Raw sockets bypass the kernel TCP stack. Paqet constructs packets manually rather than using the OS networking API. The kernel never sees a TCP connection, so there is no connection state for DPI to track.
  2. Custom TCP flags. The packets carry non-standard flag combinations that do not match any known protocol fingerprint. DPI systems looking for SSH, TLS, or HTTP handshakes find nothing recognizable.
  3. KCP reliability layer. KCP (a protocol similar to UDP-based reliability) provides ordering and retransmission on top of these raw packets. It looks like random data with unusual TCP headers.

The result: firewalls see TCP packets that do not belong to any connection they are tracking and that match no known protocol signature. Most DPI systems pass them through.


How GFW-Knocker Works

GFK uses two layers: violated TCP to get past the firewall, and QUIC tunneling inside to carry actual data.

Your Device                  Your VPS                    Internet
+--------------+            +--------------+           +----------+
|  Browser     |            |  GFK Server  |           |  Google  |
|      |       | Violated   |      |       |           |  YouTube |
|      v       |   TCP      |      v       |           |  etc.    |
|  GFK Client  | ---------> | QUIC Tunnel  | --------> |          |
|  (VIO+QUIC)  | (malformed |      |       |           |          |
|      |       |  packets)  |      v       |           |          |
| 127.0.0.1    |            |    Xray      |           |          |
|   :14000     |            |   (SOCKS5)   |           |          |
+--------------+            +--------------+           +----------+

Why DPI cannot detect it:

  1. Violated TCP. The client sends TCP packets that are intentionally malformed — wrong flags, no proper handshake, missing sequence numbers. DPI state machines expect normal TCP (SYN, SYN-ACK, ACK) and cannot track these connections. The packets pass through because the firewall does not know what to do with them.
  2. QUIC tunnel inside. Inside these violated packets, an encrypted QUIC connection carries the actual data. Even if someone captures the traffic, the payload is encrypted QUIC with authentication.
  3. Xray backend. On the server side, Xray provides the SOCKS5 proxy service. GFK handles transport; Xray handles proxying.

This two-layer approach is effective against deep packet inspection that has learned to detect KCP, Shadowsocks, and other single-layer protocols.


Comparison: paqctl vs Other Methods

Method DPI Resistance Speed Setup Difficulty Protocol
Paqet High (raw sockets + custom flags) Fast Easy KCP/TCP
GFK Very high (violated TCP + QUIC) Good Advanced TCP+QUIC
VLESS+Reality High (mimics real TLS) Fast Medium TCP/TLS
Hysteria2 Good (looks like HTTP/3) Very fast Medium QUIC/UDP
SSH Tunnel Low (easily fingerprinted) Moderate Easy TCP
WireGuard Low (known signature) Very fast Easy UDP
Shadowsocks Medium (can be detected) Fast Easy TCP/UDP
Tor Very high (onion routing) Slow Easy TCP

Prerequisites

  • A VPS with a public IP and root access (Ubuntu/Debian recommended)
  • A client machine: Windows 10/11, macOS, or Linux
  • Windows only: Npcap (the installer handles this automatically)
  • Server connection info: IP, port, and key/auth code

Server Setup

Install paqctl

SSH into your VPS and run:

curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash

The installer downloads the latest paqet release from GitHub and sets up the management commands.

Interactive Menu

Open the menu to configure your server:

sudo paqctl menu

The menu walks you through choosing a method (Paqet, GFK, or both), setting ports, and generating keys.

Management Commands

sudo paqctl menu        # Interactive setup menu
sudo paqctl status      # Check if services are running
sudo paqctl start       # Start the service
sudo paqctl stop        # Stop the service
sudo paqctl restart     # Restart the service
sudo paqctl status        # Show connection info for clients (IP, port, key)
sudo paqctl logs        # View recent logs
sudo paqctl update      # Update to the latest version
sudo paqctl health      # Run health checks
sudo paqctl uninstall   # Remove paqctl completely
sudo paqctl telegram    # Configure Telegram bot notifications

After setup, the installer displays your connection info (IP, port, key). You can also view it anytime with sudo paqctl status.


Firewall Configuration

Paqet: Open Port 8443

Paqet needs its port open in the firewall because it sends real (raw) packets that the kernel firewall inspects:

sudo ufw allow 8443/tcp
sudo ufw reload

GFK: Keep VIO Port BLOCKED

GFK's VIO port (default 45000) must stay blocked in the firewall. Do not open it with ufw.

Why? GFK uses raw sockets that operate below the kernel's network stack. The packets bypass iptables/nftables entirely — they never hit the firewall. If you open the port, you expose a raw socket listener to the internet unnecessarily.

# Verify the port is NOT open (this is correct)
sudo ufw status | grep 45000
# Should return nothing — that means it is blocked (correct)

If you accidentally opened it:

sudo ufw delete allow 45000/tcp
sudo ufw reload

Paqet Client Setup

Download

Go to the paqet releases page and download the archive for your platform. Download the .tar.gz (Linux/macOS) or .zip (Windows) archive — not a bare binary.

Platform File
Windows (x64) paqet-windows-amd64-v1.0.0-alpha.17.zip
Linux (x64) paqet-linux-amd64-v1.0.0-alpha.17.tar.gz
Linux (ARM64) paqet-linux-arm64-v1.0.0-alpha.17.tar.gz
macOS (Intel) paqet-darwin-amd64-v1.0.0-alpha.17.tar.gz
macOS (Apple Silicon) paqet-darwin-arm64-v1.0.0-alpha.17.tar.gz

Extract the archive:

# Linux / macOS
mkdir -p ~/paqet && cd ~/paqet
tar -xzf paqet-linux-amd64-v1.0.0-alpha.17.tar.gz
chmod +x paqet_linux_amd64

Configuration (config.yaml)

Create config.yaml in the same directory as the paqet binary:

role: "client"

log:
  level: "info"

socks5:
  - listen: "127.0.0.1:1080"

network:
  interface: "eth0"
  ipv4:
    addr: "192.168.1.100:0"
    router_mac: "aa:bb:cc:dd:ee:ff"

server:
  addr: "YOUR_SERVER_IP:8443"

transport:
  protocol: "kcp"
  kcp:
    mode: "fast"
    key: "YOUR_SECRET_KEY"

Field reference:

Field Description
role Always "client" for the client side
log.level "info" for normal use, "debug" for troubleshooting
socks5[].listen Local SOCKS5 proxy address. Default 127.0.0.1:1080
network.interface Network interface name. Linux: eth0 or wlan0. macOS: en0. Windows: leave empty "" for auto-detect
network.ipv4.addr Your local IP + :0. Find it with ip addr (Linux), ifconfig en0 (macOS), or ipconfig (Windows)
network.ipv4.router_mac Your gateway's MAC address. Find with ip neigh (Linux), arp -a (macOS/Windows)
server.addr Server IP and port from paqctl status
kcp.mode KCP speed mode: "fast", "fast2", "fast3", or "normal". Use "fast" for most connections. "fast3" for very lossy networks (uses more bandwidth)
kcp.key Encryption key from sudo paqctl status on the server (minimum 16 characters)

Run

Paqet requires root/admin because it uses raw sockets:

# Linux / macOS
sudo ./paqet_linux_amd64 run -c config.yaml

Your SOCKS5 proxy is now at 127.0.0.1:1080.

Configure Your Browser

Firefox (recommended):

  1. Settings > Network Settings > Manual Proxy
  2. SOCKS Host: 127.0.0.1, Port: 1080 (Paqet) or 14000 (GFK)
  3. Select SOCKS v5
  4. Check "Proxy DNS when using SOCKS v5" (prevents DNS leaks)

Chrome: Use the SwitchyOmega extension with SOCKS5 proxy 127.0.0.1:1080.

Windows Client

Windows uses .bat launcher files and requires Npcap for raw socket access.

  1. Go to the paqctl repository and download the ZIP (Code > Download ZIP)
  2. Extract and open the windows folder
  3. Right-click Paqet-Client.bat and select Run as administrator
  4. First run installs Npcap automatically (follow the installer prompts)
  5. Enter your server IP, port, and key when prompted

Alternatively, use the PowerShell script for an interactive menu:

# Run PowerShell as Administrator first
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
irm https://raw.githubusercontent.com/SamNet-dev/paqctl/main/windows/paqet-client.ps1 | iex

GFK Client Setup

GFK uses Python scripts (not compiled binaries). You need Python 3.10+ with scapy and aioquic.

Install Dependencies

# Clone the repository
git clone https://github.com/SamNet-dev/paqctl.git
cd paqctl/gfk/client

# Install Python packages
pip3 install scapy aioquic

Configuration (parameters.py)

Create parameters.py in the gfk/client directory:

# GFW-knocker client configuration
from scapy.all import conf

# Server settings
vps_ip = "YOUR_SERVER_IP"
xray_server_ip = "127.0.0.1"

# Port mappings (local_port: remote_port)
tcp_port_mapping = {14000: 443}
udp_port_mapping = {}

# VIO (raw socket) ports
vio_tcp_server_port = 45000
vio_tcp_client_port = 40000
vio_udp_server_port = 35000
vio_udp_client_port = 30000

# QUIC tunnel ports
quic_server_port = 25000
quic_client_port = 20000
quic_local_ip = "127.0.0.1"

# QUIC settings
quic_verify_cert = False
quic_idle_timeout = 86400
udp_timeout = 300
quic_mtu = 1420
quic_max_data = 1073741824
quic_max_stream_data = 1073741824
quic_auth_code = "YOUR_AUTH_CODE"
quic_certificate = "cert.pem"
quic_private_key = "key.pem"

# SOCKS proxy
socks_port = 14000

Key fields to change:

Field Description
vps_ip Your server's public IP
tcp_port_mapping Maps local port to remote port. {14000: 443} means local 14000 forwards to server port 443
vio_tcp_server_port Must match the server's VIO port (default 45000)
quic_auth_code Authentication code from paqctl status on the server

Run

# Requires root for raw sockets
sudo python3 mainclient.py

Your SOCKS5 proxy is now at 127.0.0.1:14000.

Windows GFK Client

  1. Download the paqctl ZIP from GitHub
  2. Open the windows folder
  3. Right-click GFK-Client.bat and select Run as administrator
  4. The script installs Python 3, Npcap, scapy, and aioquic automatically
  5. Enter your server IP and auth code when prompted

3X-UI Panel Integration

paqctl auto-detects existing Xray panels (3x-ui, Marzban). When it finds a running panel, it works alongside it without modifying your existing configuration.

Scenario What paqctl does
No Xray installed Installs Xray with SOCKS5 automatically
Xray panel running Keeps your panel, adds SOCKS5 inbound on a free port (e.g. 10443)
Xray installed but not running Installs its own SOCKS5 config

When a panel is detected, paqctl provides two connections automatically:

  • Panel mapping (14000:443) — for server-to-server panel traffic (vmess/vless)
  • SOCKS5 mapping (14001:10443) — for direct proxy use from a client (no v2rayN needed)

Server-to-Server Bridge

This setup routes traffic from an Iran-based panel through a GFK tunnel to a foreign panel. The end user connects to the Iran panel normally; the Iran panel forwards traffic through GFK to the foreign server.

Setup

1. Foreign server (server role):

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 inbound port). paqctl detects Xray and adds SOCKS5 alongside it.

2. Iran server (client role):

curl -fsSL https://raw.githubusercontent.com/SamNet-dev/paqctl/main/paqctl.sh | sudo bash

Choose client role. Use the exact same port mappings from the server output. Use the same auth code.

3. Update the Iran panel outbound:

Change the outbound in your Iran panel (3x-ui or Marzban) to route through the local GFK tunnel instead of connecting directly to the foreign server.

Before (direct — blocked by DPI):

{
  "tag": "vmess_out",
  "protocol": "vmess",
  "settings": {
    "vnext": [{
      "address": "FOREIGN_SERVER_IP",
      "port": 443,
      "users": [{"id": "your-uuid", "security": "auto"}]
    }]
  }
}

After (routed through GFK tunnel):

{
  "tag": "vmess_out",
  "protocol": "vmess",
  "settings": {
    "vnext": [{
      "address": "127.0.0.1",
      "port": 14000,
      "users": [{"id": "your-uuid", "security": "auto"}]
    }]
  }
}

The change: address becomes 127.0.0.1 and port becomes 14000 (the local VIO port). Everything else (UUID, protocol, encryption) stays the same. Set security/TLS to none since traffic is already encrypted inside the GFK tunnel.

Traffic flow:

End user --> Iran panel inbound --> Iran panel outbound (127.0.0.1:14000)
  --> GFK client (VIO) --> QUIC tunnel over violated TCP
  --> Foreign GFK server --> 127.0.0.1:443 (foreign panel) --> Internet

Running Both Methods Simultaneously

Paqet and GFK use different ports and can run at the same time on the same server:

# On the server, install both via paqctl menu
sudo paqctl menu
# Select both Paqet and GFK during setup

On the client side, run both clients. You get two independent SOCKS5 proxies:

  • Paqet: 127.0.0.1:1080
  • GFK: 127.0.0.1:14000

This is useful as a fallback — if one method gets blocked, switch your browser proxy to the other.


Decision Flowchart

START
  |
  v
Is your network heavily censored?
(Iran during shutdowns, China GFW, deep throttling)
  |               |
 YES              NO
  |               |
  v               v
Try GFK       Use Paqet
first         (simpler setup)
  |               |
  v               v
GFK working?  Paqet working?
  |     |       |      |
 YES    NO     YES     NO
  |     |       |      |
  v     v       v      v
Done  Try     Done   Try GFK
      Paqet          instead
  |               |
  v               v
Install BOTH for redundancy

General guidance:

  • Start with Paqet if you are not sure. It is simpler and works in most situations.
  • Switch to GFK if Paqet gets blocked or you are behind heavy DPI (Iran during major filtering events, China GFW).
  • Run both if you need maximum reliability.

Security Recommendations

Use Strong Keys

Paqet encryption keys should be at least 16 characters, random, and unique per server. Do not use example values from documentation.

# Generate a random 32-character key
openssl rand -base64 24

For GFK, the auth code is generated during server setup. Do not share it publicly.

Harden the Server with Fortify

Use Fortify to harden your VPS before or after deploying paqctl:

curl -fsSL https://raw.githubusercontent.com/SamNet-dev/fortify/main/install.sh | sudo bash

Fortify auto-detects paqctl and configures firewall rules, SSH hardening, and fail2ban without breaking your proxy setup.

Block SMTP

Block outbound SMTP to prevent your VPS from being flagged for spam (which can get your IP blacklisted):

sudo iptables -A OUTPUT -p tcp --dport 25 -j DROP
sudo iptables -A OUTPUT -p tcp --dport 587 -j DROP
sudo iptables -A OUTPUT -p tcp --dport 465 -j DROP

Test for DNS Leaks

When testing your connection, always use --socks5-hostname (not --socks5) to prevent DNS leaks:

# Correct — DNS resolves through the proxy
curl --socks5-hostname 127.0.0.1:1080 https://ifconfig.me

# WRONG — DNS leaks to your local resolver
curl --socks5 127.0.0.1:1080 https://ifconfig.me

In Firefox, make sure "Proxy DNS when using SOCKS v5" is checked (Settings > Network Settings).


Offline Installation

If GitHub is blocked in your country, you need to download the files from a machine that has access and transfer them.

Server (Offline)

  1. On a machine with internet access, download the paqctl installer script and the paqet binary from the releases page.
  2. Transfer both files to your VPS via SCP, USB, or any other method.
  3. Run the installer script locally:
chmod +x paqctl.sh
sudo bash paqctl.sh

Client (Offline)

  1. Download the correct paqet archive for your OS from the releases page (use a VPN, a friend's connection, or download on the VPS and SCP to your machine).
  2. Extract and create config.yaml manually (see the Paqet Client Setup section above).
  3. Run with sudo ./paqet run -c config.yaml.

For GFK, you also need the Python packages. On a machine with access:

pip3 download scapy aioquic -d ./packages

Transfer the packages folder, then install offline:

pip3 install --no-index --find-links=./packages scapy aioquic

Troubleshooting

Problem Cause Fix
Connection refused Server not running Run sudo paqctl status on server, then sudo paqctl start
Connection timeout Port blocked by firewall For Paqet: sudo ufw allow 8443/tcp. For GFK: verify port is NOT open (raw sockets bypass firewall)
Permission denied Not running as root/admin Linux/macOS: use sudo. Windows: Run as Administrator
"Gateway MAC not found" Router MAC not detected Find manually: arp -a (Windows/macOS) or ip neigh (Linux), enter in config
Slow speed KCP mode too conservative Change kcp.mode to "fast2" or "fast3" in config.yaml
GFK: "auth failed" Auth code mismatch Re-check quic_auth_code in parameters.py matches server output from paqctl status
Paqet works, GFK does not VIO port accidentally opened in firewall Run sudo ufw delete allow 45000/tcp && sudo ufw reload
Works on WiFi, not mobile data ISP blocks raw packets on mobile Try the other method, or use a different port
Npcap install fails (Windows) Conflict with existing install Uninstall old Npcap from Control Panel, reboot, reinstall
"Running scripts is disabled" (Windows) PowerShell execution policy Run: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Server disconnects periodically Resource exhaustion or ISP throttling Check sudo paqctl logs, ensure VPS has adequate memory
DNS leaks detected Using --socks5 instead of --socks5-hostname Use curl --socks5-hostname and enable "Proxy DNS" in Firefox

Related Guides

SamNet Open Source Tools

Tool Purpose
paqctl Censorship bypass with Paqet + GFW-Knocker (this guide)
fortify Server security hardening (auto-detects paqctl)
tunnelforge SSH tunneling with TLS obfuscation
cfray Find clean Cloudflare IPs for CDN fallback
MTProxyMax Telegram proxy manager
wg-orchestrator WireGuard VPN management
torware Tor Bridge/Relay setup

Related Tools