Refactor NFQueue verdict handling and introduce TUN device management#256
Refactor NFQueue verdict handling and introduce TUN device management#256DanielLavrushin wants to merge 62 commits into
Conversation
- Introduced a `verdictCtx` struct to encapsulate packet verdict logic, replacing direct calls to `nfqueue` in various packet processing functions. - Updated `processDnsPacket`, `handlePacket`, `handleTCPPacket`, and `handleUDPPacket` methods to utilize the new `verdictCtx` for verdict management. - Added `ApplyMasqueradeOnly` and `ClearMasqueradeOnly` functions to manage NAT masquerade rules independently of NFQUEUE. - Implemented a new `Engine` for TUN device management, including setup and teardown of routes and packet forwarding. - Created `routeManager` to handle routing logic for the TUN interface, including default route management and bypass rules. - Added `openTUN` function to encapsulate TUN device opening logic. - Enhanced `sock` package to support binding raw sockets to specific devices. - Improved error handling and logging throughout the packet processing and TUN management code.
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Complexity | 1 medium |
🟢 Metrics 448 complexity
Metric Results Complexity 448
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Pull request overview
Adds a new “TUN mode” execution path alongside the existing NFQUEUE pipeline by extracting engine-agnostic packet processing into a shared dispatch layer, plus introducing TUN device + route management and standalone NAT masquerade rule management.
Changes:
- Introduce a TUN engine that reads packets from a TUN device, runs them through the existing worker logic, and forwards accepted packets via raw sockets.
- Refactor NFQUEUE verdict handling into a
verdictCtxto share packet-processing logic between NFQUEUE callbacks and TUN ingestion. - Add “masquerade-only” helpers to manage NAT independently of NFQUEUE steering rules.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tun/tun.go | New TUN engine lifecycle, read loop, and forwarding via raw sockets |
| src/tun/route.go | New routing/ip rule/default-route management for TUN mode |
| src/tun/device.go | New /dev/net/tun open + TUNSETIFF ioctl wrapper |
| src/tables/iptables.go | Add iptables NAT masquerade apply/clear helpers |
| src/tables/common.go | Add backend-agnostic Apply/Clear “masquerade only” functions |
| src/sock/sender.go | Add raw-socket sender constructor that can bind to an egress device |
| src/nfq/verdict.go | New verdict context + worker sender init + engine-agnostic ProcessPacket entrypoint |
| src/nfq/pool.go | Add DNS pending-route cleanup to the pool cleanup loop |
| src/nfq/inc.go | Switch incoming handler to verdictCtx-based verdict management |
| src/nfq/handler.go | Factor out dispatch() and thread verdictCtx through TCP/UDP handlers |
| src/nfq/dns.go | Switch DNS handler to verdictCtx-based verdict management |
| src/main.go | Wire up TUN mode startup/shutdown and masquerade-only behavior |
| src/engine/engine.go | New small shared engine/verdict types for TUN integration |
| src/config/validation.go | Validate queue.mode and require queue.tun.out_interface in TUN mode |
| src/config/types.go | Add queue.mode and queue.tun.* configuration types |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (1)
src/sock/sender.go:69
- IPv4 bind-to-device failure aborts sender creation, but IPv6 bind-to-device failure only logs a warning and leaves the IPv6 socket active. In TUN mode this can reintroduce the routing-loop risk for IPv6. Consider disabling the IPv6 sender when SO_BINDTODEVICE fails.
}
}
return s, nil
}
…ify routing management
…and fixed DNS redirect issues
…based routing not work Fixes #257
…pture - Added a new TUN engine as an alternative to NFQUEUE for packet processing. - Implemented port-scoped first-N capture for TCP/UDP packets, capturing the first N packets on specified ports. - Removed the old selective routing mode, transitioning to a whole-default capture model. - Introduced a new capture chain in iptables for managing packet captures. - Updated route management to support the new capture mechanism, including setup and teardown processes. - Enhanced configuration options for TCP/UDP connection byte limits. - Added unit tests for new functionalities, including chunking ports and normalizing port formats. - Documented the new TUN engine features and known issues in TUN_HANDOFF.md.
|
| if device != "" { | ||
| cs, err := sock.NewSenderWithMark(0) | ||
| if err != nil { | ||
| w.sock.Close() | ||
| w.sock = nil | ||
| return err | ||
| } | ||
| w.clientSock = cs | ||
| } else { | ||
| w.clientSock = s | ||
| } |
| if err := unix.SetNonblock(fd, true); err != nil { | ||
| unix.Close(fd) | ||
| return nil, "", fmt.Errorf("set nonblock: %w", err) | ||
| } |
| if !cfg.System.Tables.SkipSetup { | ||
| if err := tables.ApplyMasqueradeOnly(&cfg); err != nil { | ||
| metrics.RecordEvent("error", fmt.Sprintf("Failed to apply masquerade: %v", err)) | ||
| return fmt.Errorf("failed to apply masquerade: %w", err) | ||
| } | ||
| tables.ApplyConntrackSysctls() | ||
| if err := tables.ApplyMSSClampOnly(&cfg); err != nil { | ||
| log.Errorf("Failed to apply MSS clamp in TUN mode: %v", err) | ||
| } | ||
| } else { | ||
| log.Infof("Skipping masquerade and conntrack sysctls (--skip-tables); the TUN engine also skips its own firewall/sysctl rules and only sets up routing") | ||
| } |
| if c.Queue.Mode != "" && c.Queue.Mode != "nfqueue" && c.Queue.Mode != "tun" { | ||
| v.add("queue.mode", "invalid", "queue mode must be 'nfqueue' or 'tun'", nil) | ||
| return v.result() | ||
| } | ||
|
|
||
| if c.Queue.Mode == "tun" && c.Queue.TUN.OutInterface == "" { | ||
| v.add("queue.tun.out_interface", "required", "tun out_interface is required in TUN mode (e.g. eth0, wan0, l2tp-vpn)", nil) | ||
| return v.result() | ||
| } |



verdictCtxstruct to encapsulate packet verdict logic, replacing direct calls tonfqueuein various packet processing functions.processDnsPacket,handlePacket,handleTCPPacket, andhandleUDPPacketmethods to utilize the newverdictCtxfor verdict management.ApplyMasqueradeOnlyandClearMasqueradeOnlyfunctions to manage NAT masquerade rules independently of NFQUEUE.Enginefor TUN device management, including setup and teardown of routes and packet forwarding.routeManagerto handle routing logic for the TUN interface, including default route management and bypass rules.openTUNfunction to encapsulate TUN device opening logic.sockpackage to support binding raw sockets to specific devices.