paqet: tunnelling traffic through raw TCP packets
Ferries Packets Across Forbidden Boundaries 👀
At a glance
- What is it?
- paqet is a Go proxy that crafts and captures TCP packets directly instead of letting the host's TCP/IP stack handle them, layering KCP and smux on top for a fast, reliable, encrypted, multiplexed transport. It is built for security research, and it is an alpha release whose configuration and interfaces may change without notice.
- Who is it for?
- Adopt paqet if you are doing network security research and need traffic that looks like ordinary TCP on the wire but does not go through the host's connection tracking, and if you can run root iptables rules on the server. Do not adopt it as a production VPN, since the README marks it as in active development with APIs and configuration that may change without notice, and do not expect it to replace a normal tunnel where a firewall is meant to see and control the flow.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The kernel is taken out of the path
Conventional applications rely on the host's TCP/IP stack, placing the kernel in the path of every connection, where it tracks each packet. paqet operates on raw packets instead. It crafts TCP packets directly and uses pcap to capture inbound ones, treating each as a self-contained, stateless datagram.
That is the whole design in two sentences, and everything else follows from it. If the kernel is not tracking the connection, then nothing in the network path that depends on tracking can see it as a connection either. The README says as much: paqet may bypass firewalls that rely on handshakes or connection tracking, which makes it useful for security research.
The traffic still looks ordinary on the wire. The packets are TCP packets, with sequence numbers and the rest, so a network monitoring a port sees a port carrying TCP traffic rather than something exotic. What is missing is the state on either side that a normal stack would maintain.
The project is described as a raw-packet proxy that tunnels traffic inside raw TCP packets, and its topics are gopacket, kcp, pcap and tcpdump, which tells you the building blocks. The dependency list confirms it, with gopacket for the packet handling, xtaci/kcp-go for the transport, xtaci/smux for multiplexing, golang.org/x/crypto for the encryption and goccy/go-yaml for the configuration format.
The kernel sends RST packets until you stop it
The most practically important section of the README is the firewall one, and it is honest in a way that is easy to miss.
Although the packets are handled at a low level, the OS kernel can still see incoming packets on the connection port and generate TCP RST packets, since it has no knowledge of the connection. Those kernel-generated resets can corrupt connection state in NAT devices and stateful firewalls, causing instability, packet drops and premature termination.
In other words, the operating system fights the tool. The server receives a SYN from a peer it has never heard of, decides that something is wrong, and resets the connection. The README's instruction is blunt: you must configure iptables on the server to prevent the kernel from interfering.
The rules come in two families. The first bypasses connection tracking for the connection port, with a NOTRACK rule in the raw table for both PREROUTING and OUTPUT:
sudo iptables -t raw -A PREROUTING -p tcp --dport <PORT> -j NOTRACK
sudo iptables -t raw -A OUTPUT -p tcp --sport <PORT> -j NOTRACKThe second family stops the kernel from sending the RST packets that would kill the session, using the mangle table.
The README also insists on a non-standard port, and explains why in a way that is easy to miss: do not use ports 80, 443 or any other standard ports, because iptables rules can also affect outgoing connections from the server. The example suggests 9999 or 8888, or other high-numbered ports. Since the rules you add for the incoming connection can also catch the traffic the server sends out, a standard port would break the server's own outbound connections.
KCP and smux turn datagrams into a transport
Sending stateless datagrams is only half the problem, since a tunnel has to be reliable and ordered enough to carry TCP traffic. That job is done by the layer above.
The README says KCP provides fast, reliable, encrypted transport, and the configuration names the transport protocol as kcp with a block setting for the encryption algorithm and a key. The configuration comments state that the current version supports only kcp as the transport protocol, which tells you the abstraction is there but the implementation is not yet plural.
The multiplexing comes from smux, which the README lists alongside KCP as providing a fast, reliable, encrypted and multiplexed transport layer. Multiplexing matters here for a specific reason: with raw packets, every packet is self-contained and the kernel is not doing the flow control, so multiple logical streams sharing one set of packets has to be handled above the transport. The dependency list has xtaci/smux v1.5.53 and xtaci/kcp-go v5.6.72, with klauspost/reedsolomon in the indirect list, which is the FEC layer that KCP uses for loss recovery.
The configuration is YAML, parsed with goccy/go-yaml, and the key setting is the same on both sides:
transport:
protocol: "kcp" # Transport protocol (currently only "kcp" supported)
kcp:
block: "aes" # Encryption algorithm
key: "your-secret-key-here" # CHANGE ME: Secret key (must match server)The client is a SOCKS5 proxy, and it needs a gateway MAC address
The client side is the part that applications talk to. The client acts as a SOCKS5 proxy server, accepting connections from applications and dynamically forwarding them through the raw TCP packets to any destination. A port forwarding mode can be used alongside it, with a local listen address, a target and a protocol of tcp or udp.
The configuration file carries the network details that a normal socket would have found for you. You set the interface, the local IPv4 address and port, and the router MAC address:
role: "client"
socks5:
- listen: "127.0.0.1:1080" # SOCKS5 proxy listen address
network:
interface: "en0" # CHANGE ME: Network interface (en0, eth0, wlan0, etc.)
ipv4:
addr: "192.168.1.100:0" # CHANGE ME: Local IP (use port 0 for random port)
router_mac: "aa:bb:cc:dd:ee:ff" # CHANGE ME: Gateway/router MAC address
server:
addr: "10.0.0.100:9999" # CHANGE ME: paqet server address and portThe router MAC address is the unusual requirement, and it comes from the raw packet approach. Because the tool crafts the packets itself, it has to fill in fields that the kernel would normally derive, and the source MAC that a frame leaves the interface with is the one the gateway would see. The README walks through finding it per platform, with ip a and ip r and arp -n on Linux, ifconfig and netstat -rn and arp -n on macOS, and ipconfig /all and arp -a on Windows, where you additionally need the Npcap device GUID in the form \Device\NPF_{GUID}, obtained with Get-NetAdapter and formatted from the InterfaceGuid.
Windows support also depends on Npcap being installed, and the prerequisites note that the libpcap development libraries must be installed on both the client and the server, with Linux binaries statically linked and macOS covered by the Xcode Command Line Tools.
The server side is mostly about not colliding with the kernel
The server configuration is shorter, and most of it is about the port. The role must be set explicitly, the listen address holds the port, and the network block has to agree with it, since the server IPv4 and port must match listen.addr, and the listen port must match the network.ipv4.addr port.
The listen line in the README carries a warning worth reading as part of the value rather than as a footnote. The comment says the server listen port must match the network.ipv4.addr port, and warns against using standard ports such as 80 and 443, because iptables rules can affect outgoing server connections. The example uses a port of 9999 and a router MAC of the same placeholder form as the client.
The result is a configuration surface that looks like a YAML file and behaves like a network device. Every value in it is a promise about how the host is wired, and the failure mode when a promise is broken is not a clear error but a connection that resets, which is the kind of problem that eats an afternoon.
The repository is small and matches the design. There is a cmd/ directory for the command entry point, an internal/ directory for the implementation, an example/ directory with client.yaml.example and server.yaml.example, a go.mod and go.sum, and the go.mod requires Go 1.27 with the gopacket, kcp, smux, cobra, yaml and crypto dependencies already noted. The command line is cobra, so the usual subcommand and help behaviour comes for free.
Where paqet is the wrong tool
The first wrong-tool case is production use, and the project says so itself. The README carries a warning that the project is in active development, that APIs, configuration formats and interfaces may change without notice, and that it should be used with caution in production environments. A tunnel that a company's remote access depends on is not a place to accept that.
The second is a network where the firewall is supposed to see the traffic. That is the same point from the other side. The tool's property is that connection-tracking firewalls cannot follow it, which is exactly what you want for research and exactly what you do not want if your security model depends on the firewall being able to account for every session. The README is clear that the configuration is more complex than a VPN but gives you finer control in return, and that trade is only worth taking for a specific reason.
The third is an environment where you cannot run root iptables rules. The whole server side depends on them, and the README is unambiguous that without them the kernel interferes and the connection state breaks. A managed host, a container without NET_ADMIN, or a platform where you do not own the kernel rules is a dead end.
There is a fourth practical point. The gateway MAC address is part of the configuration, and it changes when the network changes. A laptop that moves between networks has a different gateway, and a configuration with a hardcoded MAC in it will start misbehaving in a way that looks like a network fault rather than a stale setting.
MIT, version 1.0.0-alpha.21 and an interface that moves
The project is MIT licensed, with the LICENSE file at the repository root. The default branch is master, and the repository is not archived.
The version line is the honest signal. The releases are v1.0.0-alpha.21 from 2026-08-22, v1.0.0-alpha.20 from 2026-06-28 and v1.0.0-alpha.19 from 2026-02-24, so the project is still on a 1.0.0 alpha, more than twenty alpha releases in, with three releases spread across 2026. The last push was on 2026-10-15.
Here the version number matches the README's warning about APIs and configuration changing without notice.
The build requires Go 1.27, which is a recent toolchain floor, and the dependency set is short and legible, with gopacket for the packet layer, kcp-go and smux for the transport, cobra for the command line, goccy/go-yaml for the configuration, and golang.org/x/crypto for the encryption that the kcp block setting selects.
For a research tool that is the right shape. The scope is narrow, the mechanism is unusual, and the code is small enough to read.
Editorial conclusion
Adopt paqet if you are doing network security research and need traffic that looks like ordinary TCP on the wire but does not go through the host's connection tracking, and if you can run root iptables rules on the server. Do not adopt it as a production VPN, since the README marks it as in active development with APIs and configuration that may change without notice, and do not expect it to replace a normal tunnel where a firewall is meant to see and control the flow. Before you deploy, read the firewall section carefully, since the kernel will send RST packets until the iptables rules are in place, choose a non-standard port as the README insists, and confirm that using raw packets this way is permitted where you run it.
Frequently asked questions
What is paqet and how does it differ from a VPN?
paqet is a raw-packet proxy that tunnels traffic inside raw TCP packets. It crafts TCP packets directly and captures inbound ones with pcap, treating each as a stateless datagram, so the host's TCP/IP stack is not in the path. KCP and smux provide the reliable, encrypted, multiplexed layer on top, and the configuration is more complex than a VPN's in exchange for finer control.
Why does paqet need iptables rules on the server?
The kernel can still see incoming packets on the connection port and sends TCP RST packets because it has no knowledge of the connection, which corrupts state in NAT devices and stateful firewalls. The README requires a NOTRACK rule in the raw table for the connection port and a rule in the mangle table to drop the kernel's resets.
Which ports should a paqet server use?
Not standard ports. The README warns against 80, 443 and other standard ports because the iptables rules can also affect outgoing connections from the server, and suggests high-numbered ports such as 9999 or 8888 instead. The server listen port must also match the port in network.ipv4.addr.
What prerequisites does paqet have?
The libpcap development libraries must be installed on both the client and the server. On Linux the binaries are statically linked, on macOS the Xcode Command Line Tools provide it, and on Windows Npcap has to be installed, and the Npcap device GUID in the form \Device\NPF_{GUID} is required in the configuration.
Is paqet safe for production use?
The README carries a warning that the project is in active development, that APIs, configuration formats and interfaces may change without notice, and that it should be used with caution in production environments. The most recent release is v1.0.0-alpha.21, dated 2026-08-22.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hanselime-paqet)Was this useful?