{"id":50416138,"url":"https://github.com/bjin/phantun-dkms","last_synced_at":"2026-05-31T06:01:25.885Z","repository":{"id":350792197,"uuid":"1197162268","full_name":"bjin/phantun-dkms","owner":"bjin","description":"Kernel module re-implementation of phantun, transform UDP streams into fake-TCP streams","archived":false,"fork":false,"pushed_at":"2026-05-31T01:27:25.000Z","size":412,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-31T03:13:09.700Z","etag":null,"topics":["faketcp","kernel-module","phantun","wireguard"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bjin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-31T11:28:13.000Z","updated_at":"2026-05-31T01:27:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bjin/phantun-dkms","commit_stats":null,"previous_names":["bjin/phantun-dkms"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/bjin/phantun-dkms","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjin%2Fphantun-dkms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjin%2Fphantun-dkms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjin%2Fphantun-dkms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjin%2Fphantun-dkms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bjin","download_url":"https://codeload.github.com/bjin/phantun-dkms/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjin%2Fphantun-dkms/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33720897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["faketcp","kernel-module","phantun","wireguard"],"created_at":"2026-05-31T06:01:25.274Z","updated_at":"2026-05-31T06:01:25.879Z","avatar_url":"https://github.com/bjin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# phantun-dkms\n\n[![Latest Release](https://img.shields.io/github/v/release/bjin/phantun-dkms.svg?display_name=release)](https://github.com/bjin/phantun-dkms/releases/latest)\n[![GitHub branch status](https://github.com/bjin/phantun-dkms/actions/workflows/ci.yml/badge.svg)](https://github.com/bjin/phantun-dkms/actions/workflows/ci.yml)\n\nIf you already know [**Phantun**](https://github.com/dndx/phantun/): this is a **Linux kernel module implementation of Phantun's fake-TCP idea**.\n\nPhantun runs as a **user-space client/server** pair around a **TUN interface**. `phantun-dkms` keeps the translation in the **kernel**, intercepts **existing UDP sockets** directly, and avoids the TUN topology.\n\n## Phantun compatibility\n\n`phantun-dkms` is **not advertised as compatible with Phantun endpoints**.\n\nThe important nuance: the **basic wire packet shape is intentionally the same**, so the TCP/UDP header overhead story is the same too. For MTU budgeting, Phantun's documentation is still the right mental model.\n\nWhat changed is the **behavioral contract** around that wire format. I have not tried to make mixed `phantun` / `phantun-dkms` endpoints interoperate, and I would currently assume they **most likely will not** work seamlessly.\n\nMain reasons:\n\n- **Untested interoperability**: mixed deployments have not been validated.\n- **Randomized initiator ISN**: `phantun-dkms` randomizes the initial sequence number; Phantun historically uses `0`, which is easier for DPI to fingerprint.\n- **Symmetric role model**: `phantun-dkms` drops fixed client/server node roles and uses per-flow **initiator** / **responder** roles instead.\n- **TCP-like keepalive behavior**: `phantun-dkms` sends keepalive ACKs and tears flows down after repeated misses; that is another behavior difference that may break mixed-endpoint expectations.\n- **Other protocol-level improvements**: several behavior changes make accidental compatibility less likely, even though the fake-TCP packet shape stays close.\n\nShort version: **same broad wire shape, different enough behavior that you should treat this as kernel-to-kernel only unless proven otherwise**.\n\n\n## If you know Phantun, here are the practical differences\n\n| Topic | Phantun | `phantun-dkms` |\n|---|---|---|\n| **Where it runs** | User space | Linux kernel module |\n| **Traffic model** | TUN interface plus routing/NAT around it | Direct interception of selected existing UDP sockets |\n| **Process model** | Separate client/server binaries | No separate daemon; same module runs on both hosts |\n| **Node roles** | Fixed client and server | No node-level client/server split; each flow has initiator/responder only |\n| **Application integration** | App talks through Phantun's TUN topology | App keeps its existing UDP socket |\n| **Traffic selection** | Bind/listen topology around TUN endpoints | Selector-based ownership via `managed_local_ports` and/or `managed_remote_peers` |\n| **Full-mesh setup** | Configure a tunnel for each node pair, so a mesh grows O(n²) | Configure selectors once per node; no per-pair tunnels |\n| **Firewall/NAT plumbing** | Requires TUN-side DNAT/SNAT/masquerade setup | No Phantun-specific TUN DNAT/masquerade plumbing; module stays on the normal host path and integrates with conntrack |\n| **Inbound raw UDP policy** | Ownership handled by TUN topology | Selector-matched raw inbound UDP is dropped on non-loopback ingress |\n| **Liveness / keepalive** | No matching kernel-module keepalive behavior here | TCP-like keepalive ACKs plus missed-keepalive teardown |\n| **Protocol compatibility** | Phantun contract | Mixed Phantun / `phantun-dkms` use is **untested and likely not seamless** |\n| **Address family** | IPv4 and IPv6 | IPv4 and IPv6, with `ip_families=both/ipv4/ipv6` selection |\n\n## What still feels like Phantun\n\nThe core fake-TCP shape is still familiar:\n\n- strict 3-way handshake\n- data rides in TCP `ACK` packets carrying payload\n- `seq` / `ack` track payload bytes\n- no FIN close state machine\n- `RST` is the teardown/error signal\n\nSo if you already understand why Phantun works on the wire, you already understand most of the packet-level idea here.\n\n## Can it coexist with Phantun?\n\nYes.\n\n`phantun-dkms` explicitly ignores traffic on **loopback devices**, including UDP between local loopback endpoints. That means a local Phantun setup using `127.0.0.1` can coexist without the kernel module trying to steal it.\n\n## How to think about this project\n\nInstead of creating a TUN interface and routing traffic through it, `phantun-dkms` does this:\n\n\u003e Pick the UDP traffic to own, steal it in kernel, send fake TCP on the wire, turn inbound fake TCP back into UDP before the local app sees it.\n\nThat is the whole model.\n\n## When this is useful\n\nUse this when you want Phantun-like fake TCP, but you want:\n\n- **no TUN device**\n- **no user-space forwarding daemon**\n- your app to keep its **real UDP socket**\n- explicit control over **which local ports or remote peers** get translated\n\nTypical target: **WireGuard** or **`wireguard-go`**.\n\n## Quick start\n\n### Build \u0026 Install from source code\n\n```bash\nmake\nsudo make modules_install\n```\n\nThe static `Makefile` bootstraps `./autogen.sh` and `./configure` only when their generated files are missing or stale.\n\nIf kernel autodetection fails, pass `KDIR=/path/to/kernel/build` to `make`.\n\n### Build release artifacts locally\n\n```bash\nmake dkms\nmake dkms-deb\nmake dkms-rpm\n```\n\n### Install from DKMS package (latest release)\n\n* Arch Linux: Install AUR package [phantun-dkms](https://aur.archlinux.org/packages/phantun-dkms)\n* Debian/Ubuntu: Download and install `.deb` file from [latest release](https://github.com/bjin/phantun-dkms/releases/latest)\n* Fedora/RHEL/Rocky: Download and install the `.rpm` file from [latest release](https://github.com/bjin/phantun-dkms/releases/latest)\n* Other Distributions: Extract `.tar.gz` dkms tarball from [latest release](https://github.com/bjin/phantun-dkms/releases/latest) to `/usr/src/phantun-0.x.y`, and run `dkms add` manually\n\n### Install on NixOS from the flake\n\nAdd the flake input:\n\n```nix\ninputs.phantun-dkms = {\n  url = \"github:bjin/phantun-dkms\";\n  inputs.nixpkgs.follows = \"nixpkgs\";\n};\n```\n\nThen import the NixOS module and configure the kernel parameters with typed options:\n\n```nix\n{\n  imports = [ inputs.phantun-dkms.nixosModules.default ];\n\n  services.phantun = {\n    enable = true;\n    loadOnBoot = true;\n    managedRemotePeers = [\n      \"198.51.100.20:51820\"\n      \"[2001:db8::20]:51820\"\n    ];\n    handshakeRequest = \"hello\";\n    handshakeResponse = \"base64:d29ybGQ=\";\n    keepaliveIntervalSec = 15;\n    keepaliveMisses = 3;\n  };\n}\n```\n\n`loadOnBoot = false` leaves the package and generated modprobe configuration available for manual `modprobe phantun`, but does not add `phantun` to `boot.kernelModules`.\n\nThe `nixpkgs.follows` line makes this module use the consumer flake's `nixpkgs` input instead of keeping a second transitive `nixpkgs` pinned by this repository.\n\n\n### Simplest load: own one local UDP port\n\n```bash\nsudo modprobe phantun managed_local_ports=51820\n```\n\n### Own one exact remote peer instead\n\n```bash\nsudo modprobe phantun managed_remote_peers=198.51.100.20:51820\n```\n\n```bash\nsudo modprobe phantun managed_remote_peers='[2001:db8::20]:51820'\n```\n\n### Require both local port and remote peer\n\n```bash\nsudo modprobe phantun \\\n  managed_local_ports=51820 \\\n  managed_remote_peers=198.51.100.20:51820\n```\n\n## Traffic ownership model\n\nThe module only touches traffic that matches one or both selector lists.\n\n| Selector | Meaning | Typical use |\n|---|---|---|\n| `managed_local_ports` | Own this local UDP/TCP port | \"Translate my local WireGuard listen port\" |\n| `managed_remote_peers` | Own this exact remote `IPv4:port` or `[IPv6]:port` | \"Translate only traffic for this peer\" |\n\nRules:\n\n- **At least one** selector list must be non-empty.\n- If you configure **both**, **both must match**.\n- Selector ownership applies only to **non-loopback** traffic.\n- Raw inbound UDP that matches the selectors is dropped on **non-loopback ingress** so traffic is not delivered both as raw UDP and translated UDP.\n- `ip_families=both|ipv4|ipv6` selects which IP families are translated; it defaults to `both`. On kernels without IPv6 support, default `both` degrades to IPv4-only with a warning, while explicit `ipv6` is rejected.\n- IPv6 `managed_remote_peers` entries must be bracketed, for example `[2001:db8::20]:51820`; unbracketed IPv6 endpoints are rejected as ambiguous.\n- `managed_remote_peers` is exact-address matching. If a remote host rotates its public source address, including IPv6 privacy-address rotation, update the configured peer address or use `managed_local_ports` for server-like endpoints that should accept any remote address on the owned local port.\n- IPv6 link-local endpoint addresses are not supported. Selector-matched traffic with a link-local local or remote endpoint is rejected instead of translated.\n\n### Selector modes\n\n| Mode | What you set | Tradeoff |\n|---|---|---|\n| **Local-only** | `managed_local_ports` | Easiest and closest to Phantun's **server-side selector model**: own traffic by local service port. |\n| **Peer-only** | `managed_remote_peers` | Closest to Phantun's **client-side selector model**: own traffic by chosen remote peer. Inbound TCP ownership becomes broad for that remote `IPv4:port` or `[IPv6]:port`, so use only when that peer is dedicated to this translator. |\n| **Intersection** | Both | Most explicit and usually safest. |\n\n### Optional local TCP reservation for local-only mode\n\n`managed_local_ports` tells `phantun-dkms` which traffic to intercept. It does **not** automatically make the module the real kernel TCP owner of that port.\n\nThat matters in **local-only** mode (`managed_local_ports` set, `managed_remote_peers` empty): inbound fake TCP for the chosen port is intercepted before the normal TCP stack sees it, but another application can still successfully `bind()` / `listen()` on the same TCP port. The result is misleading ownership: the application appears to own the port, yet the fake-TCP traffic you expected to reach it is intercepted by `phantun-dkms` first.\n\nFor a WireGuard-server-style deployment, this means `managed_local_ports=51820` alone can shadow another TCP listener on port `51820` even though the listener started successfully. If that same host or namespace also runs user-space Phantun on `127.0.0.1:51820`, the default behavior is still safe because loopback traffic is ignored.\n\n`managed_remote_peers` narrows ownership to an exact remote `IPv4:port` or `[IPv6]:port`, so unrelated listeners on the same local port are not broadly shadowed in the same way. That is why `reserved_local_ports` is only honored in pure local-only mode.\n\n`reserved_local_ports` is optional and defaults to empty. The special values `off` and empty input both disable it.\n\n| Value | Meaning |\n|---|---|\n| empty / omitted | disabled (default) |\n| `off` | disabled |\n| comma-separated ports (max 64) | reserve only the listed ports that also appear in `managed_local_ports` |\n| `all` | reserve every effective `managed_local_ports` entry |\n\nRules and trade-offs:\n\n- only honored when `managed_local_ports` is set and `managed_remote_peers` is empty\n- reservation is attempted in **every network namespace where phantun attaches**\n- reservation uses wildcard kernel binds on enabled families: `0.0.0.0:\u003cport\u003e` for IPv4 and `[::]:\u003cport\u003e` for IPv6\n- wildcard reservation also blocks loopback listeners on the same port in that namespace\n- if a port is already occupied, the module stays active and logs that truthfully instead of failing the load\n\nUse `reserved_local_ports` only when you want `phantun-dkms` to proactively claim those fake-TCP ports and you are willing to give up loopback TCP coexistence on those same ports in the affected namespace(s). If you want a local WireGuard server and a user-space Phantun process to share the host by using `127.0.0.1:\u003cport\u003e`, keep this parameter unset.\n\n\n## Everyday parameters\n\n### Required selectors\n\n| Parameter | Type | Default | Meaning |\n|---|---|---:|---|\n| `managed_local_ports` | integer array, max 64 | empty | Local ports the module owns. For WireGuard, usually the local listen port. |\n| `managed_remote_peers` | string array, max 64 | empty | Exact peers in `x.y.z.w:p` or `[IPv6]:p` form. |\n| `ip_families` | string | `both` | Enabled translation families: `both`, `ipv4`, or `ipv6`. |\n\nValidation rules:\n\n- `managed_local_ports`: `1..65535`\n- `managed_remote_peers`: valid `IPv4:port` or bracketed `[IPv6]:port`\n- at least one selector list required\n\n### Optional local TCP reservation\n\n| Parameter | Type | Default | Meaning |\n|---|---|---:|---|\n| `reserved_local_ports` | string | empty | Optional local-only TCP reservation set. Empty or `off` disables it, `all` reserves every `managed_local_ports` entry, and a comma-separated list of up to 64 ports reserves only the listed `managed_local_ports` subset. Ignored unless `managed_local_ports` is set and `managed_remote_peers` is empty. |\n### Optional timing and behavior\n\n| Parameter | Default | Meaning |\n|---|---:|---|\n| `handshake_request` | empty | Optional initiator payload sent as first fake-TCP payload. |\n| `handshake_response` | empty | Optional responder payload; effective only when `handshake_request` is also set. |\n| `handshake_timeout_ms` | `1000` | Handshake retransmit timeout. |\n| `handshake_retries` | `6` | Maximum handshake retry count before `RST` teardown. |\n| `keepalive_interval_sec` | `30` | Idle period before sending keepalive ACK. |\n| `keepalive_misses` | `3` | Unanswered keepalives allowed before teardown. |\n| `hard_idle_timeout_sec` | `300` | Hard upper bound for idle flow lifetime. |\n| `reopen_guard_bytes` | `4194304` | Minimum sequence-space distance before reopening same tuple. |\n| `half_open_limit` | `4096` | Maximum concurrent half-open flows per network namespace. New SYN-created or outbound half-open flows beyond this limit are rejected until existing half-open flows establish or time out. |\n| `replacement_quarantine_ms` | `3000` | Previous-generation quarantine window after tuple replacement. Matching old-generation packets are silently dropped during this window. |\n| `replacement_protect_ms` | `0` (auto) | Established-initiator bare-SYN replacement protection window. During the window, aligned bare replacement SYNs to an established initiator are silently dropped to suppress stale simultaneous-initiation loser SYNs. After the window expires, normal replacement handling resumes. |\n\n### Shaping payload formats\n\n`handshake_request` and `handshake_response` accept:\n\n| Form | Example | Meaning |\n|---|---|---|\n| Plain string | `HELLO` | Send bytes as-is |\n| Hex | `hex:deadbeef` | Decode remaining text as hex |\n| Base64 | `base64:YWJj` | Decode remaining text as Base64 when the target kernel supports it |\n\nInvalid hex is ignored safely. Invalid Base64, or Base64 on kernels without in-kernel Base64 support, is ignored safely with a kernel log warning.\n\n## Common setups\n\n### Own a WireGuard port\n\n```bash\nsudo modprobe phantun managed_local_ports=51820\n```\n\n### Own a WireGuard port, but only for one peer\n\n```bash\nsudo modprobe phantun \\\n  managed_local_ports=51820 \\\n  managed_remote_peers=198.51.100.20:51820\n```\n\n### Add optional request/response shaping hints\n\n```bash\nsudo modprobe phantun \\\n  managed_local_ports=51820 \\\n  managed_remote_peers=198.51.100.20:51820 \\\n  handshake_request=HELLO \\\n  handshake_response=WORLD\n```\n\n### Persist across reboots\n\nCreate `/etc/modprobe.d/phantun.conf`:\n\n```text\noptions phantun \\\n  managed_local_ports=51820 \\\n  managed_remote_peers=198.51.100.20:51820\n```\n\nThen:\n\n```bash\nsudo modprobe phantun\n```\n\n## Operational notes for Phantun users\n\n| Topic | What changes here |\n|---|---|\n| **No TUN plumbing** | Do not copy Phantun's TUN DNAT/SNAT/masquerade setup into this project. |\n| **Conntrack** | The module stays on the normal host path and integrates with conntrack instead of creating a separate TUN routing topology. |\n| **Loopback** | Loopback traffic is still left alone by the data path, so default local Phantun-on-loopback setups can coexist. Only an effective `reserved_local_ports` wildcard bind in pure local-only mode blocks loopback listeners on the same port in that namespace; ignored or failed reservations do not. |\n| **MTU** | Same basic fake-TCP packet overhead as Phantun; Phantun's MTU guidance still applies. |\n| **Handshake buffering** | During handshake, the module queues at most **one** outbound UDP packet per flow; later packets may be dropped and must rely on normal app retransmission. |\n| **Shaping semantics** | `handshake_request` / `handshake_response` are hints, not a verified sub-protocol. |\n| **Keepalive** | `phantun-dkms` has TCP-like keepalive behavior; that is another reason mixed Phantun / `phantun-dkms` endpoints should not be assumed to interoperate. |\n\n## Runtime stats\n\nThe module exports counters under:\n\n```text\n/sys/module/phantun/stats/\n```\n\nExample:\n\n```bash\ncat /sys/module/phantun/stats/flows_created\ncat /sys/module/phantun/stats/rst_sent\n```\n\n### Useful counters\n\nCounters are monotonic. Some counters are aggregates and a single packet/event\ncan increment both an aggregate and a more specific reason counter:\n\n- `udp_queue_full_dropped`, `udp_raw_inbound_dropped`, and\n  `udp_translation_failed_dropped` are also counted in `udp_packets_dropped`.\n- `tcp_misaligned_syn_rejected` and `tcp_unknown_tuple_rejected` are also\n  counted in `tcp_protocol_rejected`.\n- `oversized_payloads_dropped` covers both directions: outbound oversized UDP is\n  also counted in `udp_packets_dropped`; inbound oversized fake-TCP is also\n  counted in `tcp_protocol_rejected` when the module rejects it with RST.\n- These reason counters are useful labels, not a full partition. They will not\n  always add up to the aggregate counter.\n\n| Stat file | Meaning |\n|---|---|\n| **Flow lifecycle and capacity** | |\n| `flows_created` | Flow objects successfully inserted into the flow table. |\n| `flows_established` | Flows that reached `ESTABLISHED`. |\n| `flows_current` | Flow objects currently present in the flow table. |\n| `half_open_rejected` | Valid half-open openers rejected because the per-netns half-open limit was full. |\n| `handshake_retries_exhausted` | Half-open flows torn down after the handshake retransmit budget ran out. |\n| `established_liveness_timeouts` | Established flows torn down after missing too many keepalives. |\n| **Replacement and simultaneous-init recovery** | |\n| `replacements_accepted` | Established flows that accepted a valid bare, aligned replacement SYN on the same tuple. |\n| `replacement_quarantine_dropped` | Delayed previous-generation packets silently dropped during the replacement quarantine window. Bare SYNs are not quarantine drops. |\n| `replacement_protect_dropped` | Established initiator replacement SYNs silently dropped while the replacement-protect window was active. |\n| `collisions_won` | Simultaneous-initiation collisions where the local side kept initiator role. |\n| `collisions_lost` | Simultaneous-initiation collisions where the local side switched to responder role. |\n| **Shaping and control payloads** | |\n| `request_payloads_injected` | `handshake_request` payloads injected by the module. |\n| `response_payloads_injected` | `handshake_response` payloads injected by the module. |\n| `shaping_payloads_dropped` | Reserved first-payload slots hidden from the UDP app by handshake shaping. |\n| **RST and UDP packet accounting** | |\n| `rst_sent` | Fake-TCP RST packets successfully sent. A RST is often a reaction to a rejection or teardown; use the rejection/drop counters to tell why it was sent. |\n| `udp_packets_queued` | Selected outbound UDP packets accepted into a flow's one-skb queue. Queue-full drops are counted separately. |\n| `udp_packets_dropped` | Aggregate UDP datagrams consumed by the module and not successfully queued, translated, or reinjected. |\n| `udp_queue_full_dropped` | Selected outbound UDP dropped because the flow's one-skb queue was already occupied. Also increments `udp_packets_dropped`. |\n| `udp_raw_inbound_dropped` | Selector-owned raw inbound UDP intentionally dropped in `PRE_ROUTING` to avoid raw and translated duplicate delivery. Also increments `udp_packets_dropped`. |\n| `udp_translation_failed_dropped` | Selected outbound UDP consumed after local translation/open/send plumbing failed. Also increments `udp_packets_dropped`; half-open admission-limit rejects are counted by `half_open_rejected` instead. |\n| **Fake-TCP rejection and validation** | |\n| `tcp_protocol_rejected` | Aggregate owned fake-TCP packets rejected as invalid for the current protocol/state-machine context. Check narrower counters below for common reasons. |\n| `tcp_misaligned_syn_rejected` | Owned bare SYNs rejected because `seq % 4095 != 0`. Also increments `tcp_protocol_rejected`. |\n| `tcp_unknown_tuple_rejected` | Owned fake-TCP packets with no live flow rejected because they were not valid new openers. Also increments `tcp_protocol_rejected`; misaligned bare SYNs use `tcp_misaligned_syn_rejected` instead. |\n| `bad_checksum_dropped` | Fake-TCP packets dropped due to invalid TCP checksum. These are not counted as protocol rejections. |\n| `oversized_payloads_dropped` | Payloads too large for module limits. Outbound oversized UDP also increments `udp_packets_dropped`; inbound oversized fake-TCP also increments `tcp_protocol_rejected` when rejected with RST. |\n\n## Build, reload, unload\n\n| Task | Command |\n|---|---|\n| Build | `make` |\n| Refresh compile database | `make compile_commands` |\n| Install module | `sudo make modules_install` |\n| Load module | `sudo modprobe phantun ...` |\n| Unload module | `sudo rmmod phantun` |\n\n## Limits and current status\n\n- IPv4 and IPv6 are supported, with `ip_families=both|ipv4|ipv6` selecting active translation families.\n- Linux kernel compatibility: from `5.10` to `7.1`.\n- Mixed **Phantun** / **`phantun-dkms`** deployments are **untested** and should be treated as **likely non-seamless**.\n- **No FIN close state machine**.\n- This is a **kernel-to-kernel protocol variant** in practice, even though the basic packet shape stays close to Phantun.\n- First payloads reserved for shaping may be intentionally hidden from the UDP application.\n- Missing, delayed, duplicated, or lost shaping payloads do not by themselves fail the connection.\n\nFor protocol internals and state-machine details, see [**`DESIGN.md`**](./DESIGN.md).\n\n## License\n\nProject license: **GPL-2.0-or-later**, see `LICENSE` file\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjin%2Fphantun-dkms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbjin%2Fphantun-dkms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjin%2Fphantun-dkms/lists"}