From cleech at redhat.com Mon Apr 6 18:27:07 2026 From: cleech at redhat.com (Chris Leech) Date: Mon, 6 Apr 2026 11:27:07 -0700 Subject: Kernel ML-KEM implementation plans In-Reply-To: <20260331001358.GA5190@sol> References: <5F9ACD7A-F3B8-463A-A00E-28F68819A66C@gmail.com> <20260331001358.GA5190@sol> Message-ID: <20260406-e1d94afb79556186f06749f4@redhat.com> On Mon, Mar 30, 2026 at 05:13:58PM -0700, Eric Biggers wrote: > On Mon, Mar 30, 2026 at 06:41:46PM -0500, Ryan Appel wrote: > > Hello all, > > > > Looking through the mail archives I see no information on an > > implementation of ML-KEM that has been planned, except for leancrypto > > attempting to make a Key-Agreement Scheme a Key-Encapsulation > > Mechanism. > > > > Is there a plan to implement a KEM interface at this point? Is this > > something that needs support? How could someone contribute to this? > > We don't add new algorithms preemptively, but rather only when an > in-kernel user comes along. Otherwise there's a risk that the code will > never be used. > > Do you have a specific in-kernel user in mind? I haven't actually heard > anyone specifically say they need ML-KEM in the kernel yet. > > I guess the obvious use case would be WireGuard. But that would require > a new WireGuard protocol version that replaces X25519 with something > like X25519MLKEM768. It's going to be up to the WireGuard author > (Jason) to decide whether that's in the roadmap for WireGuard. > > Also maybe Bluetooth, though it seems the spec for that is yet to be > defined? > > Anyway, point is, before it makes sense to consider possible > implementation strategies, there needs to be a plan to actually use it. The NVMe fabrics authentication protocol will need a PQC replacement for it's FFDHE use. There is not a specification update for that yet. - Chris From mail at aparcar.org Thu Apr 9 14:31:55 2026 From: mail at aparcar.org (Paul Spooren) Date: Thu, 9 Apr 2026 23:31:55 +0900 Subject: Adding message type 5/6 for PQC (was Re: Export noise primitives for additional "chain key ratcheting") In-Reply-To: <9E8ACE91-126B-41BD-BCE2-8B54DCE78B97@aparcar.org> References: <9E8ACE91-126B-41BD-BCE2-8B54DCE78B97@aparcar.org> Message-ID: Hello again, To follow up my previous email, I gave it a bit more thoughts. Two new messages types now strike me as an easier migration path. I wrote the design and mangled it through an AI for readability. I?d be interested if other people have similar ideas or pursue entirely different approaches for PQC. Heads up, dealing with such big keys (~500kb) breaks this nice and clean WireGuard feel. However, to stay compatible with existing scripts, the design outlined below still allows addressing peers with their ?classical? public key, while peer setup requires the full path. Anyway, for those who care: ## Motivation A sufficiently powerful quantum computer running Shor's algorithm can break Curve25519 ECDH, allowing an attacker to: - Decrypt recorded WireGuard handshakes ("harvest now, decrypt later") - Recover static keys from captured initiations and impersonate peers WireGuard's Noise IK handshake could be augmented with post-quantum key exchange to protect against this threat while retaining full backward compatibility with existing deployments. ## Approach We add two new message types (5 and 6) that extend the existing Noise IKpsk2 handshake with a hybrid post-quantum layer. The classical Noise IK steps run first, unchanged, followed by two additional KEM operations that mix post-quantum shared secrets into the session key. The design is hybrid: even if the PQC algorithms are broken, the classical X25519 security remains. The PQC layer can only add entropy, never weaken. ### Algorithm Choice - **Classic McEliece 460896** for static peer authentication. Code-based cryptography with 40+ years of cryptanalysis. Conservative choice for long-term identity keys. Decapsulation is fast (~40?s); the tradeoff is a large public key (~524 KB). - **ML-KEM-512** (FIPS 203) for ephemeral forward secrecy. Lattice-based, NIST-standardized. Fresh keypair per handshake ensures that compromising static keys cannot decrypt past sessions. Compact: 800-byte public key, 768-byte ciphertext. ### Wire Format ``` Type 5 ? PQC Initiation (1104 bytes): [type:4][sender:4][ephemeral:32][enc_static:48][enc_timestamp:28] [mce_ciphertext:156][mlkem_encaps_key:800] [mac1:16][mac2:16] Type 6 ? PQC Response (1032 bytes): [type:4][sender:4][receiver:4][ephemeral:32][enc_nothing:16] [mce_ciphertext:156][mlkem_ciphertext:768][enc_empty:16] [mac1:16][mac2:16] ``` Backward compatible: existing WireGuard implementations silently drop unknown message types. Classical peers continue using types 1-4 without modification. ### Protocol Flow **Type 5 creation (initiator):** Phase 1 ? classical Noise IK, identical to Type 1: 1. Generate ephemeral X25519 key, mix into chain 2. DH(ephemeral, responder_static) ? encrypt initiator's static key 3. DH(initiator_static, responder_static) ? encrypt timestamp Phase 2 ? post-quantum augmentation: 4. Domain separation: mix PQC construction string into chain key 5. McEliece encapsulate to responder's static McEliece key ? 156-byte ciphertext + 32-byte shared secret, mixed into chain key via KDF 6. ML-KEM keygen ? 800-byte encapsulation key sent in message, 1632-byte decapsulation key held in handshake state **Type 6 creation (responder):** Phase 1 ? classical response (e, ee, se, psk, {}), identical to Type 2. Phase 2 ? post-quantum augmentation: 4. McEliece encapsulate to initiator's static McEliece key ? shared secret mixed into chain key 5. ML-KEM encapsulate using initiator's ephemeral encapsulation key ? shared secret mixed into chain key 6. Encrypt empty payload for transcript authentication Both sides derive identical session keys from the combined classical + PQC chain key, then proceed with the normal WireGuard transport. ### PQC-Aware MAC1 For Type 5/6, the mac1 key derivation includes the responder's McEliece public key hash: ``` pqc_mac1_key = BLAKE2s(classical_mac1_key || BLAKE2s(mce_pubkey)) ``` This tightens the DoS boundary: only peers who possess the responder's full PQC public key (~524 KB) can send valid Type 5 messages. Classical Type 1/2 mac1 is unchanged. ## Key Management ### No Separate PQC Private Key The McEliece keypair is derived deterministically from the existing WireGuard private key: ``` seed = BLAKE2s(wg_private_key || "wg-pqc-mceliece-seed") mce_sk, mce_pk = McEliece460896_KeyGen(seed) ``` One secret to protect. No additional key storage. Changing the WireGuard private key automatically rotates the PQC identity. ### Unified PublicKey Field There is no separate PQC configuration key. The standard `PublicKey` field handles both classical and PQC peers: - **44 base64 characters** (32 bytes decoded): classical Curve25519 key - **~700 KB base64** (524,192 bytes decoded): classical key + McEliece public key, concatenated Since McEliece public keys are too large for config file lines or netlink messages, if a PublicKey value starts with `/`, it is read from that file path: ```ini [Interface] PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= [Peer] PublicKey = /etc/wireguard/peer1.pub AllowedIPs = 10.0.0.2/32 Endpoint = 203.0.113.1:51820 ``` A new `wg pqcpubkey` command generates the key file: ```sh wg genkey | tee /etc/wireguard/private | wg pqcpubkey > /etc/wireguard/peer1.pub ``` This reads a private key from stdin (same UX as `wg pubkey`) and outputs the combined base64 blob. ### PQC Enforcement When a peer is configured with a PQC public key, classical Type 1 initiations from that peer are silently rejected. There is no way to downgrade a PQC-configured peer to classical-only. No explicit toggle is needed ? the presence of the McEliece key implies PQC-only. ## What We Explicitly Do Not Do - No separate PQC configuration keys or toggles - No modification to the classical Noise IK protocol - No changes to the transport data path (Type 4) > On 1. Apr 2026, at 05:14, Paul Spooren wrote: > > Hi, > > I?m looking into hardening WireGuard against quantum computers, specifically how to extend the Noise-based handshake. > > A bit of background, while PSK injection with external daemons for forward secrecy, exists, that?s extra software running, exposing extra ports etc. Modifying a Rust/Go implementation is easier than the Kernel, but my background is running things on WiFi routers, so Kernel is preferred. That said, I?d like to extend the current WireGuard message format and attach PQC without exceeding the IPv6 MTU of 1280 bytes. In literature I don?t find definitive a PQC handshake standard, however combining ML-KEM512 for forward secrecy and McEliece460896 for static long-term keys does exist in practice[1] and fits into WireGuard init and response messages. Alternatively, sntrup653 could be used for forward secrecy without PQ authentication, similar to Signal's PQXDH[2]. Possibly new primitives/schemes are developed, with smaller public keys and ciphertexts. > > Just today I read an email about ML-KEM and the Kernel; none of these cryptographic primitives are (to my knowledge) part of the Linux Kernel, making a ?new? protocol version of WireGuard more difficult to implement and further out in the future. > > I wondered if WireGuard could export some of the noise primitives like mix_hash and mix_key to allow ?one way? (ratchet) modifications of the chaining key and ?append only" bytes to the outgoing packet (PQ pubkey, ciphertext). After appending bytes, WireGuard takes over again and calculates the MAC, proceeding as usual. The "ratcheting? Kernel module would work similar to the existing PSK approach, it adds additional data to the chaining key, however it can?t downgrade it (except crashing the Kernel). Another approach could be to add netlink handling for an active daemon, this would at least reduce the open ports and network complexity. > > Yet another way to have PQ WireGuard could be to produce one's own modules like WolfGuard did the recently[3] with AES/FIPS, however I thought to ask anyway. > > Thanks, > Paul > > [1]: https://rosenpass.eu/docs/rosenpass-project/whitepaper/ > [2]: https://signal.org/docs/specifications/pqxdh/ > [3]: https://github.com/wolfSSL/wolfGuard From Jason at zx2c4.com Fri Apr 10 14:20:51 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Fri, 10 Apr 2026 16:20:51 +0200 Subject: [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released Message-ID: Hey folks, I generally don't send announcement emails for the Windows software, because the built-in updater takes care of notifying the relevant users. But because this hasn't been updated in so long, and because of recent news articles, I thought it'd be a good idea to notify the list. After a lot of hardwork, we've released an updated Windows client, both the low level kernel driver and api harness, called WireGuardNT, and the higher level management software, command line utilities, and UI, called WireGuard for Windows. There are some new features -- such as support for removing individual allowed IPs without dropping packets (as was added already to Linux and FreeBSD) and setting very low MTUs on IPv4 connections -- but the main improvement is lots of accumulated bug fixes, performance improvements, and above all, immense code streamlining due to ratcheting forward our minimum supported Windows version [1]. These projects are now built in a much more solid foundation, without having to maintain decades of compatibility hacks and alternative codepaths, and bizarre logic, and dynamic dispatching, and all manner of crust. There have also been large toolchain updates -- the EWDK version used for the driver, the Clang/LLVM/MingW version used for the userspace tooling, the Go version used for the main UI, the EV certificate and signing infrastructure -- which all together should amount to better performance and more modern code. But, as it's our first Windows release in a long while, please test and let me know how it goes. Hopefully there are no regressions, and we've tested this quite a bit -- including on Windows 10 1507 Build 10240, the most ancient Windows that we support which Microsoft does not anymore -- but you never know. So feel free to write me as needed. As always, the built-in updater should be prompting users to click the update button, which will check signatures and securely update the software. Alternatively, if you're installing for the first time or want to update immediately, our mini 80k fetcher will download and verify the latest version: - https://download.wireguard.com/windows-client/wireguard-installer.exe - https://www.wireguard.com/install/ And to learn more about each of these two Windows projects: - https://git.zx2c4.com/wireguard-windows/about/ - https://git.zx2c4.com/wireguard-nt/about/ Finally, I should comment on the aforementioned news articles. When we tried to submit the new NT kernel driver to Microsoft for signing, they had suspended our account, as I wrote about first in a random comment [2] on Hacker News in a thread about this happening to another project, and then later that day on Twitter [3]. The comments that followed were a bit off the rails. There's no conspiracy here from Microsoft. But the Internet discussion wound up catching the attention of Microsoft, and a day later, the account was unblocked, and all was well. I think this is just a case of bureaucratic processes getting a bit out of hand, which Microsoft was able to easily remedy. I don't think there's been any malice or conspiracy or anything weird. I think most news articles currently circulating haven't been updated to show that this was actually fixed pretty quickly. So, in case you were wondering, "but how can there be a new WireGuard for Windows update when the account is blocked?!", now you know that the answer is, "because the account was unblocked." Anyway, enjoy the new software, and let me know how it works for you. Thanks, Jason [1] https://lists.zx2c4.com/pipermail/wireguard/2026-March/009541.html [2] https://news.ycombinator.com/item?id=47687884 [3] https://x.com/EdgeSecurity/status/2041872931576299888 From Jason at zx2c4.com Fri Apr 10 21:42:02 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Fri, 10 Apr 2026 23:42:02 +0200 Subject: [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released In-Reply-To: References: Message-ID: If you're a tiny percentage of users running older builds of Windows 10 and are seeing in your logs, "[MGR] Update checker: The parameter is incorrect." in WireGuard for Windows v0.6, you'll need to run the fetcher to get back on track. Download and run https://download.wireguard.com/windows-client/wireguard-installer.exe and you should be all set (and will get v0.6.1 installed). If you're not seeing that in your logs, you don't need to do anything. Sorry about this! Growing pains. Jason From leon at darkk.net.ru Fri Apr 10 16:28:00 2026 From: leon at darkk.net.ru (Leonid Evdokimov) Date: Fri, 10 Apr 2026 19:28:00 +0300 Subject: WireGuard obfuscation & active probing: staying virtuous under pressure Message-ID: Hi list, I want to share an experiment on active probing of WireGuard. Observation: a relatively small burst of replayed handshake packets can reliably force WireGuard into "Under Load" mode for ~1 second. During this period, WireGuard responds to all handshake attempts (including replays) with Cookie messages. Summary ======= This does not break WireGuard itself, but it appears to affect most WireGuard-specific obfuscation layers I've looked at (xt_wgobfs, evrim-patch, swgp-go, ClusterM/wg-obfuscator, AmneziaWG, Mullvad's LWO, gutd). This distinguisher does not give censors absolute confidence. However, Frolov, Wampler and Wustrow have demonstrated a conceptually similar timeout-based distinguisher for TCP-based Probe-resistant Proxies at NDSS'20. This jar of Cookies seems to be in good company. Active probing is a well-known and realistic threat for an obfuscated protocol. E.g. Russia used it against Telegram proxies back in 2018 and still uses it in 2026. Same story with China and Shadowsocks. Iran? You name it. I'm describing the attack, exploring possible mitigations for in-tree and out-of-tree obfuscators, propose an alternative DoS mitigation based on TOTP-like identity, and speculate about some ideas to make WireGuard implementations more obfuscation-friendly. The rest of the letter may take ?20 minutes to read. I'm sorry for it being that wordy yet I hope I've managed to structure it in a readable way. I don't consider the mitigation complete and would appreciate feedback on its feasibility and alternatives. Set and setting =============== A common design for WireGuard obfuscation is to run a fully encrypted protocol on top of WireGuard, optionally with additional disguise. This aligns with the "turn the stream into noise" approach Jason mentioned in the "Let's talk about obfuscation again" thread at https://lists.zx2c4.com/pipermail/wireguard/2018-September/003295.html Such obfuscators typically rely on a long-term obfuscation key (OBFSK), exchanged out of band and used for symmetric encryption (weaker constructions are used as well). In practice, OBFSK is often shared across a clique of peers, partly because Cookie messages are sent before peer identity is known. The obfuscated WireGuard fights two distinct attackers with different goals & capabilities: "Censor": observes traffic and can replay it, but does not know OBFSK. Censor wants to reveal an obfuscated WireGuard endpoint. "DoSer": may know OBFSK and responder.static_public, and may be a legitimate peer capable of generating arbitrary handshake initiations. DoSer is a malicious competitor and/or user wanting to disrupt service. Encryption of cleartext, authentication of padding and shaping noise into a stream of plausible packets is out of scope of this letter. This Cookie jar already gets too big on its own. Cookies as distinguisher ======================== An active prober can replay captured handshake packets to force WireGuard to talk, triggering ?Under Load? mode. Once triggered, WireGuard replies with Cookie messages to any handshake with valid mac1, including replays(!). Two properties make this useful as a distinguisher: - the transition is easy to trigger with a short burst - the "Under Load" state persists for ~1 second (Go and Linux) I have not rigorously compared this behavior against other UDP services under similar load, but I assume it is sufficiently distinctive. WireGuard-Go starts sending Cookies after ~128 queued handshakes (1/8 of default queue size 1024), Linux kernel implementation uses a queue of 4096, so the threshold is ~512. One way to trigger "Under Load" is to send a paced "train" of handshakes with a low interpacket gap. It works surprisingly well both in LAN and over the Internet. The numbers I got are summarized in the table below. WireGuard under test | Train | Train rate | Steady rate | RTT -----------------------+-------+------------------+ ------------+------- Core i7-6600U x2, Go | 200 | 35k pps, 59 Mbit | 12,000 pps | LAN MikroTik RB951G-2HnD | 750 | 35k pps, 59 Mbit | 640 pps | LAN Celeron J1900, FreeBSD | 550 | 50k pps, 84 Mbit | ? | 3 ms UpCloud VM, EPYC 7543 | 700 | 50k pps, 84 Mbit | ? | 14 ms Amnezia-1.5, kmod-awg | 2000 | 50k pps, 84 Mbit | ? | 47 ms Experiment details ================== Celeron machine was located in the same city as the load generator (Russia, St.Petersburg), but within a different ISP. UpCloud VM was in a nearby country (Sweden). AmneziaWG box was "far away" in Western Europe. The train speed is expressed with packet rate instead of interpacket gap as that's what MikroTik Traffic Generator sets. RB3011UiAS-RM was used as a load generator for the experiments. Some installations might need other tools as RouterOS limits /tool/traffic-generator header length to 256 bytes. E.g., AmneziaWG adding more than 66 bytes of padding can't be tested with it. Unfortunately, pktgen in mainline Linux had some issues with custom payloads, that's why RouterOS was used. While 2000 packets might sound like a lot, it's just 350 KiB of traffic. It's an unnoticeable volume of traffic for a VPN hub and/or "exit node". It is an inexpensive amount of traffic for a modern active prober. It's in the same ballpark as The Guardian index page (gziped) being 150 KiB, as measured without additional css/js/img assets. More boring way to fill the queue is to saturate the worker thread doing handshake processing. Running Device.ConsumeMessageInitiation takes 0.13 ms on Intel Core i7-6600U. Thus, this CPU is expected to handle at most ~7700 pps of handshakes per core. That correlates well with the numbers above. Mitigation challenges ===================== Mitigating active probing at the obfuscation layer is possible, but significantly harder out-of-tree than in-tree: - The obfuscator needs to preserve SrcIP for WireGuard's rate limiting. - Forwarding Cookies preserves DoS protection but exposes a probing signal. - Dropping Cookies removes the distinguisher but breaks legitimate handshakes under load (clients cannot compute mac2). - Peer identity is not available before WireGuard processes the packet. Handling Cookies in the obfuscator requires: - tracking mac1 - decrypting per-IP Cookies - maintaining per-endpoint state to update mac2 Details below. Lacking SrcIP preservation collapses all traffic to an external IP of the obfuscator, typically 127.0.0.1. Number of handshakes with valid mac2 is rate-limited to 20pps Under Load. Thus, DoSer scheduling a handshake "train" every 1s gets DoS for all users. It's possible to limit the number of in-flight handshake_initiation packets between obfuscation and WireGuard layers to avoid Cookie response being triggered. It's a poor-man mitigation: it protects against burst-based probing, but the undersized queue does not protect from DoS. More on that below. Naive drop of Cookies at the obfuscation layer opens WireGuard layer to the following DoS attack: as soon as Under Load condition is triggered, WireGuard layer would demand mac2 and all(!) the clients will be unable to progress with handshake till Under Load is gone as they can't compute mac2. Go and Linux versions stay in Under Load state for one second. Fighting "censor" alone is relatively easy. E.g. add coarse UTC timestamps, limit handshake validity to ?30 seconds, keep some fixed-size replay filter (e.g. a Bloom filter of a size depending on a number of configured peers), and that should be enough. DoSer is a different beast. I suggest using temporary Peer Identity to fight DoSer in absence of Cookies. TOTP-based DoS mitigation ========================= Adding clocked Peer ID (ClkID) to an obfuscation-layer envelope effectively introduces a temporary, TOTP-like, pre-DH identifier. It trades some of WireGuard's identity-hiding properties for earlier filtering. Responder being Under Load may use ClkID for quick drop of invalid ClkIDs and as a rate-limit key instead of (isMac2Valid, SrcIP) condition. ClkID might be HASH(LABEL_CLKID || Epoch || initiator.static_public || responder.static_public || p2p.PSK) Epoch might be int(UTC.Seconds / 120); 120 comes from RekeyAfterTime and Cookie lifetime. It's worth investigating if 128 saves a measurable amount of CPU cycles: cloudflare/boringtun Cookie emitter assumes it's worth it. Am I right that ClkID does not worsen Identity-hiding properties if we factor UDP metadata in? ClkID is essentially a one-time ID under normal conditions and it's only reused for retries within a 2min interval. The latter implies that ClkID has to be encrypted by an obfuscator, but that's out of scope of this writeup. ClkID opens the possibility for a powerful attacker mounting targeted DoS against a specific user via rate-limiting at the obfuscation layer. That needs knowledge of semi-public receiver.OBFSK paired with capability to observe obfuscated traffic. DoSer knows OBFSK but can't listen traffic, and censor does not know OBFSK otherwise the obfuscation game is already lost. ClkID demands PSK to be unique for each pair of connected WireGuard interfaces to avoid DoS through impersonation within the clique of peers. That's one common setup, but default WireGuard also has PSK=0^256. I've observed one large deployment reusing non-zero PSKs across a clique of users. Initiator's and Responder.static_public are mixed into ClkID to make deployment of these kind "working", but "insecure" against malicious clique members. "Working" as in "not suffering from an extra rate-limit imposed by shooting themselves in the foot". Lack of that mixin will lead to violation of principle of least astonishment as adding few more peers to such a deployment may lead to unexpected handshake drops within the mesh. The price responder pays to support ClkID-based dispatch is computation of Blake2s-256 for each configured peer every two minutes. That's ?300ms spent every 2min for (1 << 20) peers on a Skylake Intel Core i7-6600U. It's close to 0.25% of a single CPU core time, it does not sound prohibitive for an obfuscated protocol. That still has few open problems: thundering herd; CPU usage penalty for an completely idle interface; CPU usage penalty for an interface with low number of active peers & high number of peers configured. I would appreciate feedback whether the proposed ClkID approach is a reasonable direction, or if there are simpler alternatives I am missing. WireGuard & identity ==================== Identity-hiding property of the WireGuard handshake makes it non-trivial to rate-limit based on the initiator's identity as the identity is unsealed only after DH and that's exactly the CPU-consuming operation. However, identity-hiding is not absolute in WireGuard: E.g. observer knowing responder.static_public may passively confirm the expected identity of a responder using mac1. They still have to see the flow in both directions to use response as a confirmation (not "proof"). But that's exactly how TSPU is to be deployed (TSPU is Russian tsar-in-the-middle filtering equipment) and that's how jabber.ru XMPP traffic was intercepted. Assuming that censor is a bi-directional observer sounds plausible to me for the purpose of threat modeling. E.g. observer with responder.static_private key seized may decrypt initiator.static_public. E.g. observer may use receiver_index to keep track of user's network location when the user is roaming from one IP to another. So, if I understand WireGuard's identity-hiding correctly, the main goal is to make two user's sessions non-linkable if the user is silent(!) for an extended period of time AND connection metadata does not allow for session linkage: e.g. user roams to another IP AND rotates listen-port. IIUC, this extended period is ?3min of silence, as RejectAfterTime states. One may say that obfuscation slightly improves privacy of WireGuard as it encrypts the WireGuard header. Now, as a client moves between networks, a passive observer of both network paths will need OBFSK to determine the fact that old and new IP addresses belong to the same system using the unencrypted receiver_index of the packets. However, listen-port on both sides often stays the same while one of the peers is roaming, so anonymity set is still "all the users of the Endpoint roaming at the same time". NTP Client Data Minimization draft mentions similar problem at https://datatracker.ietf.org/doc/html/draft-ietf-ntp-data-minimization-04#section-4.1 ClkID alternatives ================== SrcIP is a bad key for rate-limiting as IP ownership verification becomes unreliable without Cookies. Established sessions might have their SrcIP verified, but new ones are not. Roaming with session being active transfers the ownership to the new IP, but roaming to the new IP after two minutes of silence keeps SrcPort at most. Active Queue Management combined with Proof-of-Work schemes like hashcash is another way to make an attack more costly to DoSer, but they come with their own drawbacks. First, PoW penalises the legitimate user as well, especially under bad network weather as we lose ability to distinguish handshake timeout due to natural packet loss from the need to mint more zeroes & work harder. Second, designing PoW schemes in the era of ASIC miners might be tricky. E.g. Antminer KA3-166T mining Blake2s-256 produces 52,000 MH/W, GPU AMD RX 6650 XT does 70 MH/W while Intel Core i7-6600U CPU does just 1 MH/W. ClkID performance ================= When the responder is completely idle, it may put ClkID check after DH and avoid spending time on regular re-computation of ClkIDs for all configured peers. When the responder is active and transits to Under Load it gets tricky. On one hand, it will already take 17ms to do DH for these 128 handshakes. On another hand, these 17ms may be rather spent computing ?44,000 ClkIDs given the fact that Blake2s-256 takes ~340 less time than DH. What's worse, the censor might try to use RTT as a signal to distinguish VPN doing NAT from full-mesh Tailscale-like end-to-end VPN and RTT bias "Under Load". It's unclear to me if it's possible to have a unified ClkID behavior suitable both for a smallish interface with 256 peers and for WireGuardMaxxer with (1<<20) peers. I don't know the quasi-optimal way to go. One might be to have several "escalation" steps. Here are some back of the napkin calculations: First one is being idle & doing nothing. Being idle is good both for battery consumption and overall mental health. Second one is an active interface with a TINY number of peers, e.g. ?100 peers. 100 comes from Blake2s-256 being 340 times more computationally expensive than one DH exchange and need to compute ?one Epoch. This interface can compute ClkID in the Handshake thread and be just fine. Third one is an active interface with OKAY number of peers, e.g. under ?2'500. These interfaces have latency penalty less than 1ms for computing the full ClkID table as the interface transitions to "Under Load" state. OKAY value is not necessary a compile-time constant, it might also be a runtime estimate to keep latency under 1ms depending on something like LoadAverage value. Fourth one is an active interface with a HUGE number of peers, something between OKAY and MAX_PEERS_PER_DEVICE. These interfaces can't afford to spend a few hundred milliseconds to process the next handshake while transitioning to Under Load state, so they should refresh ClkID tables in the background. OBFSK scoping ============= Handling Cookie messages at the obfuscator layer and dropping Cookie messages from the on-the-wire part of the obfuscated protocol opens a possibility to bind OBFSK to a listening port on ingress and to an endpoint on egress instead of having the same key shared among the whole clique. Scoped OBFSK brings little value to typical setups. Peers in full-mesh already know all OBFSK keys. All peers in hub-and-spoke share OBFSK for the hub. However, scoped OBFSK aligns well with WireGuard agility allowing other topologies. Obfuscator handling Cookies on its own might set OBFSK to some F(peer), e.g. defaulting to HASH(LABEL_OBFS || peer.static_public). However, an out-of-tree obfuscator has to recover peer identity from mac1 (or receiver_index), which is not directly available after packet emission. This leads to cache-based or computationally expensive lookup methods doing trial hashing over all known peers. Both methods are also prone to ToC/ToU races. DoS with undersized queue ========================= First, it's tricky to make a robust estimator of in-flight handshakes count. The obfuscator gets a handshake_response if the handshake_initiation was handled, but it's challenging to distinguish "handshake not yet handled" from "handshake dropped" cases. The handshakes are not guaranteed to be handled in FIFO order, e.g. WireGuard-Go starts a per-CPU RoutineHandshake worker. Overestimating the number of in-flight handshakes lowers handshake throughput available for "good" users. The DoSer knowing responder.static_public might craft 512 different handshakes with out-of-date encrypted_timestamp, send them and force the obfuscator on the responder side into a hard choice. When should it be ready to relay the next handshake of the legitimate user to the WireGuard layer given the complete silence? Underestimating the number of in-flight handshakes and putting WireGuard backend Under Load leaves the obfuscator with a choice between plain DoS and computational DoS. Plain DoS may come from cookies being dropped by obfuscator and legitimate users being unable to do handshakes for 1s. Computational DoS comes from cookies being decrypted & used without any IP validation. If I do math correctly, sustaining a computational DoS against a somewhat modern CPU still needs ~10 Mbit/s of handshakes per attacked core. That's not a lot, but disabling the Cookie-based protection in such a convoluted way does not sound too bad for certain setups. Although, it's still suboptimal for a deployment of a scale of a sizable VPN service provider. WireGuard over Shadowsocks-2022 =============================== TL;DR: Too much crypto + deployment challenges. Shadowsocks is a good solution against censor, but it strips 40 more bytes from MTU and AEADs data twice: XChaCha20-Poly1305 of Shadowsocks + ChaCha20-Poly1305 of WireGuard burning twice as much carbon credits. Performance matters: e.g. Mullvad introduces LWO claiming performance improvement over Shadowsocks. WireGuard over Shadowsocks might drop SrcIP. This allows DoSer talking to WireGuard through Shadowsocks to trigger rate-limiting of 127.0.0.1 (or other "external" IP address of the Shadowsocks daemon). Common recipes on the web do nothing special about this threat. I expect WireGuard-Go and Linux kernel implementations to drop handshakes exceeding the 20pps limit and DoS legitimate users if Under Load is triggered. Other implementations behave differently, more below. IIUC, Shadowsocks deployments typically assume trusted PSK holders and that's a weaker assumption than WireGuard's threat model. WireGuard assumes peer being potentially malicious (e.g. limited to 50 INITIATIONS_PER_SECOND) and responder.static_public being known to an attacker (attacker gets Cookies & juices at most 20 PACKETS_PER_SECOND out of a single SrcIP they control). The only major installation of Shadowsocks+WireGuard I know is Mullvad. I assume, Mullvad uses Rust gotatun implementation, so I've chosen not to explore DoS-ability of it in-the-wild as gotatun takes a non-mainline approach to anti-DoS Cookies. Iron-rich Cookies recipes ========================= Two Rust implementations behave differently regarding the Cookies compared to WireGuard-Go and Linux kernel. mullvad/gotatun checks Under Load condition on per-SrcIP basis, not with per-device queue waterline like Linux & Go do. It makes sense given that the development is led by Mullvad: the goal might be to avoid "leaking" "Under Load" state to the network. It makes gotatun vulnerable to SrcIP spoofing, however the vulnerability is unlikely exploitable for DoS purposes: it's just a per-IP slot allocation in a HashMap that is .clear()'ed every second without doing memory reallocation. The only vector I see here is OOM through spoofing. Saturating 10 Gbit/s interface with handshakes will probably lead just to ~1?2GiB of HashMap being allocated. So, it's an unrealistic OOM trigger. cloudflare/boringtun does completely different things. It flips global "Under Load" flag after 10 handshakes within a second, and I don't see post-mac2 per-IP rate limiter at all. I feel like both gotatun and boringtun may warrant further analysis regarding their CPU DoS resistance in certain setups given the different way to handle Under Load conditions. Sidenotes ========= Sidenote #1: WireGuard Go ratelimiter.Allow() should probably follow Linux kernel WireGuard implementation and use IPv6 as /64 subnet. Sidenote #2: WireGuard web page on DoS mitigation seems to be out of date, https://www.wireguard.com/protocol/#dos-mitigation says: > In order for the server to remain silent unless it receives a valid > packet, while under load, all messages are required to have a MAC that > combines the receiver's public key and optionally the PSK as the MAC > key. IIUC, PSK is not currently used for DoS-related mac1/mac2, it's mixed into KDF for handshake_response.encrypted_nothing and SymmetricSession. Am I getting it wrong? What's for WireGuard? ===================== I have not built a full PoC yet, so these ideas are exploratory. Still, I'd like to discuss a few changes that could make WireGuard easier to integrate with obfuscation layers, without changing its core. 1) Optional per-device Send-Cookie toggle Allowing WireGuard to disable the built-in Cookie sender on a per-device basis would let an obfuscation layer take full responsibility for DoS protection. This avoids forcing out-of-tree obfuscators to choose between: - interpreting Cookie messages, or - leaking a distinguisher, or - breaking handshakes under load. This would be conceptually similar to net.ipv4.tcp_syncookies allowing delegating DoS tradeoffs to the operator. 2) Optional exposure of a receiver identifier Obfuscators currently lack access to peer identity, which makes per-peer configuration and rate limiting difficult without trial hashing over all peers. An optional mechanism to expose a receiver-side identifier in outgoing packets (e.g., HASH(static_public) or ClkID conveyed via the mac2 field) could allow obfuscators to integrate with WireGuard's identity model without modifying handshake semantics. Question: Would changes of this scope be acceptable for the reference implementation, or is this better kept entirely out-of-tree? Would it make sense to develop a more detailed proposal? Acknowledgements ================ I'd like to thank Danil Bezborodov (@ShaTie), Egor Koleda (@radioegor146) and Dmitry Nourell (hey at flo.boo) for valuable suggestions and corrections. I'm also thankful to Schei?e und Pisse Stiftung for donations supporting the work on this idea, to Amnezia VPN led by Mazay Banzaev for real-word data on WireGuard usage, to B4CKSP4CE hackerspace for equipment used for benchmarks. And for the "WireGuard itself is derived from an exfiltration mechanism of mine" as Jason Donenfeld told at https://lists.zx2c4.com/pipermail/wireguard/2018-September/003295.html for providing an excellent and well-thought protocol to build upon. -- WBRBW, Leonid Evdokimov, https://darkk.net.ru tel:+79816800702 PGP: 6691 DE6B 4CCD C1C1 76A0 0D4A E1F2 A980 7F50 FAB2 From syzbot at syzkaller.appspotmail.com Mon Apr 13 15:01:12 2026 From: syzbot at syzkaller.appspotmail.com (syzbot) Date: Mon, 13 Apr 2026 08:01:12 -0700 Subject: [PATCH] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit In-Reply-To: <20260413150024.1003490-1-shardul.b@mpiricsoftware.com> Message-ID: <69dd0538.a00a0220.468cb.0049.GAE@google.com> > wg_netns_pre_exit() manually acquires rtnl_lock() inside the > pernet .pre_exit callback. This causes a hung task when another > thread holds rtnl_mutex - the cleanup_net workqueue (or the > setup_net failure rollback path) blocks indefinitely in > wg_netns_pre_exit() waiting to acquire the lock. > > Convert to .exit_rtnl, introduced in commit 7a60d91c690b ("net: > Add ->exit_rtnl() hook to struct pernet_operations."), where the > framework already holds RTNL and batches all callbacks under a > single rtnl_lock()/rtnl_unlock() pair, eliminating the contention > window. > > The rcu_assign_pointer(wg->creating_net, NULL) is safe to move > from .pre_exit to .exit_rtnl (which runs after synchronize_rcu()) > because all RCU readers of creating_net either use maybe_get_net() > - which returns NULL for a dying namespace with zero refcount - or > access net->user_ns which remains valid throughout the entire > ops_undo_list sequence. > > Reported-by: syzbot+pFBD3bslSSshiJCd3rxy at syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?id=cb64c22a492202ca929e18262fdb8cb89e635c70 > Signed-off-by: Shardul Bankar > --- > drivers/net/wireguard/device.c | 6 ++---- > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c > index 46a71ec36af8..eb854c5294a3 100644 > --- a/drivers/net/wireguard/device.c > +++ b/drivers/net/wireguard/device.c > @@ -411,12 +411,11 @@ static struct rtnl_link_ops link_ops __read_mostly = { > .newlink = wg_newlink, > }; > > -static void wg_netns_pre_exit(struct net *net) > +static void wg_netns_exit_rtnl(struct net *net, struct list_head *dev_kill_list) > { > struct wg_device *wg; > struct wg_peer *peer; > > - rtnl_lock(); > list_for_each_entry(wg, &device_list, device_list) { > if (rcu_access_pointer(wg->creating_net) == net) { > pr_debug("%s: Creating namespace exiting\n", wg->dev->name); > @@ -429,11 +428,10 @@ static void wg_netns_pre_exit(struct net *net) > mutex_unlock(&wg->device_update_lock); > } > } > - rtnl_unlock(); > } > > static struct pernet_operations pernet_ops = { > - .pre_exit = wg_netns_pre_exit > + .exit_rtnl = wg_netns_exit_rtnl > }; > > int __init wg_device_init(void) > -- > 2.34.1 > I see the command but can't find the corresponding bug. The email is sent to syzbot+HASH at syzkaller.appspotmail.com address but the HASH does not correspond to any known bug. Please double check the address. From ryan.appel.333 at gmail.com Thu Apr 2 17:08:17 2026 From: ryan.appel.333 at gmail.com (Ryan Appel) Date: Thu, 2 Apr 2026 12:08:17 -0500 Subject: Kernel ML-KEM implementation plans In-Reply-To: <20260331011133.GB5190@sol> References: <20260331001358.GA5190@sol> <7507DE2E-1507-4D03-B6EF-9C139BBF34F8@gmail.com> <20260331011133.GB5190@sol> Message-ID: <8721F1CE-0E84-4A2B-816F-0A4485BA808E@gmail.com> Another potential and likely use case is Wi-Fi. WPA3 supports both SAE-PK (which currently uses ECDSA-P256 and will likely migrate to ML-DSA or other, And WPA3 enterprise supports EAP, which uses the IKE Diffie-Hellman groups, which already have added support for (pending finalization) ML-KEM groups. Of course the spec will have to be updated, but it?s highly likely that at least ML-KEM-512 will be supported. The actual use of the algorithm is as simple as calling it instead of ECDH, but in theory, we typically care very much about the difference between key agreement and key exchange. The major difference on a code front is that with ECDH, you input a public and private key, and get out a shared key. But with ML-KEM, you input a public key, and get out a shared key, and a cipher text. Or you input a private key and a cipher text and get out the same shared key. (Encapsulation -> one input, two outputs) (Decapsulation -> two inputs, one output) I understand that there is a chicken and egg scenario where there?s need to wait for the need before developing, but something at least to consider for the roadmap. > On Mar 30, 2026, at 8:11?PM, Eric Biggers wrote: > > On Mon, Mar 30, 2026 at 07:44:55PM -0500, Ryan Appel wrote: >> WireGuard was my big implementation user. > > Any more details on this? Googling for research papers shows that there > have indeed been several proposals for quantum-resistant WireGuard. But > some use algorithms other than ML-KEM. Others don't modify the kernel > code but rather do the key establishment in userspace. I haven't looked > into the details, but it also sounds like it's not as simple as swapping > out the algorithm, either. > > I think step 1 is work out some plan with the WireGuard folks. Which > may or may not turn out to involve in-kernel ML-KEM. > >> I also know that VMware uses the kernel crypto space for many of its >> crypto operations. I do not know when they will want ML-KEM and if >> they will want it only within BoringCrypto or OpenSSL, but if there is >> need for it in the market before it can be developed then that makes >> sense. > > That code isn't upstream though, right? So even if hypothetically they > (will?) need ML-KEM in the kernel (for what?), that doesn't count for > upstream purposes. > > - Eric From shardul.b at mpiricsoftware.com Mon Apr 13 15:00:24 2026 From: shardul.b at mpiricsoftware.com (Shardul Bankar) Date: Mon, 13 Apr 2026 20:30:24 +0530 Subject: [PATCH] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit Message-ID: <20260413150024.1003490-1-shardul.b@mpiricsoftware.com> wg_netns_pre_exit() manually acquires rtnl_lock() inside the pernet .pre_exit callback. This causes a hung task when another thread holds rtnl_mutex - the cleanup_net workqueue (or the setup_net failure rollback path) blocks indefinitely in wg_netns_pre_exit() waiting to acquire the lock. Convert to .exit_rtnl, introduced in commit 7a60d91c690b ("net: Add ->exit_rtnl() hook to struct pernet_operations."), where the framework already holds RTNL and batches all callbacks under a single rtnl_lock()/rtnl_unlock() pair, eliminating the contention window. The rcu_assign_pointer(wg->creating_net, NULL) is safe to move from .pre_exit to .exit_rtnl (which runs after synchronize_rcu()) because all RCU readers of creating_net either use maybe_get_net() - which returns NULL for a dying namespace with zero refcount - or access net->user_ns which remains valid throughout the entire ops_undo_list sequence. Reported-by: syzbot+pFBD3bslSSshiJCd3rxy at syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?id=cb64c22a492202ca929e18262fdb8cb89e635c70 Signed-off-by: Shardul Bankar --- drivers/net/wireguard/device.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 46a71ec36af8..eb854c5294a3 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -411,12 +411,11 @@ static struct rtnl_link_ops link_ops __read_mostly = { .newlink = wg_newlink, }; -static void wg_netns_pre_exit(struct net *net) +static void wg_netns_exit_rtnl(struct net *net, struct list_head *dev_kill_list) { struct wg_device *wg; struct wg_peer *peer; - rtnl_lock(); list_for_each_entry(wg, &device_list, device_list) { if (rcu_access_pointer(wg->creating_net) == net) { pr_debug("%s: Creating namespace exiting\n", wg->dev->name); @@ -429,11 +428,10 @@ static void wg_netns_pre_exit(struct net *net) mutex_unlock(&wg->device_update_lock); } } - rtnl_unlock(); } static struct pernet_operations pernet_ops = { - .pre_exit = wg_netns_pre_exit + .exit_rtnl = wg_netns_exit_rtnl }; int __init wg_device_init(void) -- 2.34.1 From shardul.b at mpiricsoftware.com Mon Apr 13 15:12:32 2026 From: shardul.b at mpiricsoftware.com (Shardul Bankar) Date: Mon, 13 Apr 2026 20:42:32 +0530 Subject: [PATCH v2] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit Message-ID: <20260413151232.1004611-1-shardul.b@mpiricsoftware.com> wg_netns_pre_exit() manually acquires rtnl_lock() inside the pernet .pre_exit callback. This causes a hung task when another thread holds rtnl_mutex - the cleanup_net workqueue (or the setup_net failure rollback path) blocks indefinitely in wg_netns_pre_exit() waiting to acquire the lock. Convert to .exit_rtnl, introduced in commit 7a60d91c690b ("net: Add ->exit_rtnl() hook to struct pernet_operations."), where the framework already holds RTNL and batches all callbacks under a single rtnl_lock()/rtnl_unlock() pair, eliminating the contention window. The rcu_assign_pointer(wg->creating_net, NULL) is safe to move from .pre_exit to .exit_rtnl (which runs after synchronize_rcu()) because all RCU readers of creating_net either use maybe_get_net() - which returns NULL for a dying namespace with zero refcount - or access net->user_ns which remains valid throughout the entire ops_undo_list sequence. Reported-by: syzbot+f2fbf7478a35a94c8b7c at syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?id=cb64c22a492202ca929e18262fdb8cb89e635c70 Signed-off-by: Shardul Bankar --- v2: Fix incorrect Reported-by email address drivers/net/wireguard/device.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 46a71ec36af8..eb854c5294a3 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -411,12 +411,11 @@ static struct rtnl_link_ops link_ops __read_mostly = { .newlink = wg_newlink, }; -static void wg_netns_pre_exit(struct net *net) +static void wg_netns_exit_rtnl(struct net *net, struct list_head *dev_kill_list) { struct wg_device *wg; struct wg_peer *peer; - rtnl_lock(); list_for_each_entry(wg, &device_list, device_list) { if (rcu_access_pointer(wg->creating_net) == net) { pr_debug("%s: Creating namespace exiting\n", wg->dev->name); @@ -429,11 +428,10 @@ static void wg_netns_pre_exit(struct net *net) mutex_unlock(&wg->device_update_lock); } } - rtnl_unlock(); } static struct pernet_operations pernet_ops = { - .pre_exit = wg_netns_pre_exit + .exit_rtnl = wg_netns_exit_rtnl }; int __init wg_device_init(void) -- 2.34.1 From doug.hs at proton.me Mon Apr 13 21:41:11 2026 From: doug.hs at proton.me (Douglas Silva) Date: Mon, 13 Apr 2026 21:41:11 +0000 Subject: Android app: export configuration as a password-protected zip file In-Reply-To: <3uPzijiGmCFwzmGThO2Z2EhiLTEw1w-Jqx3eC5wTpEjGUfbAivno4-eIG9UV4Xqc9tUFSdKkobsWPYRBke-QuqkqGwylaPy4-ALihwtoe7Y=@proton.me> References: <3uPzijiGmCFwzmGThO2Z2EhiLTEw1w-Jqx3eC5wTpEjGUfbAivno4-eIG9UV4Xqc9tUFSdKkobsWPYRBke-QuqkqGwylaPy4-ALihwtoe7Y=@proton.me> Message-ID: <5OnExJASKzYVA1fiNjP_WBN5i5seMIJpGVOZrdCItPeaYKrmNr4Wist_6oHN8eYSDBM2JzSd7DooSQH4faJ4kt9ySoDMSZlmFRokIMPKJ04=@proton.me> An update: it seems that Seedvault can already backup this app's data, because it pretends to do a device-to-device transfer. [1] That's good enough for those running the likes of LineageOS, but I still think the password-protected zip would still be useful in case you don't like to use Auto Backup. [1] https://github.com/seedvault-app/seedvault/discussions/997#discussioncomment-16437606 On Saturday, August 9th, 2025 at 09:08, Douglas Silva wrote: > Greetings. > > This is a feature request for the Android app. I'd like to suggest two alternatives to address the issue of exporting an unencrypted zip-file containing all your private keys into the Downloads folder. > > 1. Export a password-protected zip-file instead, allowing us to choose a password in the app settings. This is what Syncthing does nowadays. > > 2. Optionally let Android Backup pick up our config (disabled by default). Google Drive isn't the only back-end available. Ever heard of Seedvault? It's the default on systems like LineageOS or CalyxOS. Seedvault does encrypted backups to any location; even offline, to a flash stick. Aegis Authenticator uses it, as long as the backup is advertised as encrypted. See [1], [2] and [3] and [4]. > > [1] https://developer.android.com/identity/data/autobackup#EnablingAutoBackup > [2] https://developer.android.com/identity/data/autobackup#define-device-conditions > [3] https://github.com/seedvault-app/seedvault/wiki/FAQ#why-do-some-apps-not-allow-to-get-backed-up > [4] https://github.com/beemdevelopment/Aegis/blob/master/app/src/main/AndroidManifest.xml#L22 > > > For option 1 (password-protected zip), I'd also like to suggest the addition of (optional) automatic exports to a chosen folder, to facilitate automatic backups with an external tool such as Syncthing. The messaging app Signal does something like this to export your messages (encrypted) and keep the last five versions of it. > > Thank you. From Jason at zx2c4.com Tue Apr 14 13:28:37 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Tue, 14 Apr 2026 15:28:37 +0200 Subject: [PATCH v2] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit In-Reply-To: <20260413151232.1004611-1-shardul.b@mpiricsoftware.com> References: <20260413151232.1004611-1-shardul.b@mpiricsoftware.com> Message-ID: Hi Shardul, On Mon, Apr 13, 2026 at 5:13?PM Shardul Bankar wrote: > > wg_netns_pre_exit() manually acquires rtnl_lock() inside the > pernet .pre_exit callback. This causes a hung task when another > thread holds rtnl_mutex - the cleanup_net workqueue (or the > setup_net failure rollback path) blocks indefinitely in > wg_netns_pre_exit() waiting to acquire the lock. > > Convert to .exit_rtnl, introduced in commit 7a60d91c690b ("net: > Add ->exit_rtnl() hook to struct pernet_operations."), where the > framework already holds RTNL and batches all callbacks under a > single rtnl_lock()/rtnl_unlock() pair, eliminating the contention > window. > > The rcu_assign_pointer(wg->creating_net, NULL) is safe to move > from .pre_exit to .exit_rtnl (which runs after synchronize_rcu()) > because all RCU readers of creating_net either use maybe_get_net() > - which returns NULL for a dying namespace with zero refcount - or > access net->user_ns which remains valid throughout the entire > ops_undo_list sequence. > > Reported-by: syzbot+f2fbf7478a35a94c8b7c at syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?id=cb64c22a492202ca929e18262fdb8cb89e635c70 > Signed-off-by: Shardul Bankar Thanks. Applied to the wireguard tree, and also added the missing __net_exit and __read_mostly annotations in the process. Jason From kuba at kernel.org Tue Apr 14 15:18:24 2026 From: kuba at kernel.org (Jakub Kicinski) Date: Tue, 14 Apr 2026 08:18:24 -0700 Subject: [PATCH v2] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit In-Reply-To: References: <20260413151232.1004611-1-shardul.b@mpiricsoftware.com> Message-ID: <20260414081824.0edf6113@kernel.org> On Tue, 14 Apr 2026 15:28:37 +0200 Jason A. Donenfeld wrote: > Thanks. Applied to the wireguard tree, and also added the missing > __net_exit and __read_mostly annotations in the process. Hi Jason, while we have you - do you have a PR for us for wireguard? We're going to be sending the net-next PR later today.. From Jason at zx2c4.com Tue Apr 14 15:40:03 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Tue, 14 Apr 2026 17:40:03 +0200 Subject: [PATCH v2] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit In-Reply-To: <20260414081824.0edf6113@kernel.org> References: <20260413151232.1004611-1-shardul.b@mpiricsoftware.com> <20260414081824.0edf6113@kernel.org> Message-ID: On Tue, Apr 14, 2026 at 5:18?PM Jakub Kicinski wrote: > > On Tue, 14 Apr 2026 15:28:37 +0200 Jason A. Donenfeld wrote: > > Thanks. Applied to the wireguard tree, and also added the missing > > __net_exit and __read_mostly annotations in the process. > > Hi Jason, while we have you - do you have a PR for us for wireguard? > We're going to be sending the net-next PR later today.. Sent! From kuba at kernel.org Tue Apr 14 15:44:06 2026 From: kuba at kernel.org (Jakub Kicinski) Date: Tue, 14 Apr 2026 08:44:06 -0700 Subject: [PATCH v2] wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit In-Reply-To: References: <20260413151232.1004611-1-shardul.b@mpiricsoftware.com> <20260414081824.0edf6113@kernel.org> Message-ID: <20260414084406.779336af@kernel.org> On Tue, 14 Apr 2026 17:40:03 +0200 Jason A. Donenfeld wrote: > On Tue, Apr 14, 2026 at 5:18?PM Jakub Kicinski wrote: > > > > On Tue, 14 Apr 2026 15:28:37 +0200 Jason A. Donenfeld wrote: > > > Thanks. Applied to the wireguard tree, and also added the missing > > > __net_exit and __read_mostly annotations in the process. > > > > Hi Jason, while we have you - do you have a PR for us for wireguard? > > We're going to be sending the net-next PR later today.. > > Sent! Thanks! (I'll apply in a couple of hours once the CI had its way with it.) From oho790114 at gmail.com Tue Apr 14 05:57:27 2026 From: oho790114 at gmail.com (=?UTF-8?B?7Jik7ZWc7JuF?=) Date: Tue, 14 Apr 2026 14:57:27 +0900 Subject: WireGuard Windows 0.6.1 - Existing tunnels disappeared and ZIP import not working Message-ID: Hello, We are experiencing two critical issues after updating WireGuard on Windows (version 0.6.1): 1) All existing tunnels disappeared after update - Previously configured tunnels are no longer visible - Configurations folder appears empty 2) Cannot import new tunnels (ZIP file) - ZIP config files are not visible in import dialog - Even using "*.*" filter, files do not appear - Files definitely exist in the selected folder This issue is affecting multiple users. Please check if this is a known issue or regression. Thank you. From oho790114 at gmail.com Tue Apr 14 06:24:35 2026 From: oho790114 at gmail.com (=?UTF-8?B?7Jik7ZWc7JuF?=) Date: Tue, 14 Apr 2026 15:24:35 +0900 Subject: WireGuard Windows 0.6.1 - Existing tunnels disappeared and ZIP import not working Message-ID: Hello, I am reporting two critical issues after updating WireGuard on Windows (version 0.6.1): 1) Existing tunnels disappeared after update - All previously configured tunnels are no longer visible - The Configurations folder appears empty: C:\Program Files\WireGuard\Data\Configurations\ 2) Cannot import new tunnels (ZIP files) - ZIP configuration files are not visible in the import dialog - Even using "*.*" filter, no files are shown - The files definitely exist in the selected folder This issue is affecting multiple users in a production environment. Please confirm whether this is a known issue or a regression in version 0.6.1. Thank you. From oho790114 at gmail.com Wed Apr 15 12:51:58 2026 From: oho790114 at gmail.com (=?UTF-8?B?7Jik7ZWc7JuF?=) Date: Wed, 15 Apr 2026 21:51:58 +0900 Subject: WireGuard Windows 0.6.1 regression after recent update (tunnels lost & import failure) Message-ID: Hello, I am reporting a critical issue with WireGuard on Windows (version 0.6.1). We have observed that this issue started occurring consistently after recent updates (approximately 1 days ago). Before that, some systems updated to 0.6.1 without problems, but now the issue occurs 100% of the time after updating. Issues observed: 1) Existing tunnels are lost after update - Previously configured tunnels disappear - Configurations folder appears empty 2) Cannot import new tunnels - ZIP and config files are not visible in the import dialog - Even using "*.*" filter, files do not appear - Files definitely exist in the selected folder This is affecting multiple users in a production environment. It seems that something may have changed recently in the update package or behavior, even though the version number remains 0.6.1. Please confirm if there has been any recent change or if this is a known regression. Thank you. From oho790114 at gmail.com Thu Apr 16 00:23:30 2026 From: oho790114 at gmail.com (=?UTF-8?B?7Jik7ZWc7JuF?=) Date: Thu, 16 Apr 2026 09:23:30 +0900 Subject: WireGuard Windows 0.6.1 - Partial fix but ZIP import still broken Message-ID: Hello, I am reporting an update regarding the issue with WireGuard for Windows (version 0.6.1). It seems that today's update partially improved the previous problem: - Existing tunnels are no longer disappearing after update (this appears to be fixed) However, there is still a critical issue remaining: 1) Importing tunnels is broken, especially ZIP files - ZIP files are not visible in the import dialog - Even when using "*.*" filter, the files do not appear - Drag and drop does not work at all This issue is consistently reproducible. As a result, users cannot add new tunnels after installation or update. This is still a serious problem for production use. Please check: - Why ZIP import is not working - Whether this is a known issue - When this will be fixed Thank you. From oho790114 at gmail.com Thu Apr 16 00:37:39 2026 From: oho790114 at gmail.com (=?UTF-8?B?7Jik7ZWc7JuF?=) Date: Thu, 16 Apr 2026 09:37:39 +0900 Subject: WireGuard Windows 0.6.1 - Timeline of issues (tunnels lost & import still broken) Message-ID: Hello, I would like to report a clear timeline of issues observed with WireGuard for Windows (version 0.6.1). April 14: - After updating, all existing tunnels disappeared - Importing new tunnels failed - ZIP files were not visible - "*.*" filter did not help - Drag and drop did not work April 16: - Existing tunnels no longer disappear after update (possibly improved) - However, importing new tunnels is still not working - ZIP files are still not visible in the import dialog - "*.*" filter does not work - Drag and drop still fails At this point: - It is unclear whether the tunnel disappearance issue is fully fixed or not - The import issue remains critical and consistently reproducible Impact: - Users cannot add new tunnels after installation or update - This is affecting a production VPN service with multiple users Please confirm: - Whether there was a recent change in the update package - Whether the import issue is a known bug - When a fix can be expected Thank you. From Jason at zx2c4.com Thu Apr 16 03:27:17 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Thu, 16 Apr 2026 05:27:17 +0200 Subject: WireGuard Windows 0.6.1 - Timeline of issues (tunnels lost & import still broken) In-Reply-To: References: Message-ID: On Thu, Apr 16, 2026 at 09:37:39AM +0900, ??? wrote: > Hello, > > I would like to report a clear timeline of issues observed with > WireGuard for Windows (version 0.6.1). > > April 14: > - After updating, all existing tunnels disappeared > - Importing new tunnels failed > - ZIP files were not visible > - "*.*" filter did not help > - Drag and drop did not work > > April 16: > - Existing tunnels no longer disappear after update (possibly improved) > - However, importing new tunnels is still not working > - ZIP files are still not visible in the import dialog > - "*.*" filter does not work > - Drag and drop still fails > > At this point: > - It is unclear whether the tunnel disappearance issue is fully fixed or not > - The import issue remains critical and consistently reproducible > > Impact: > - Users cannot add new tunnels after installation or update > - This is affecting a production VPN service with multiple users > > Please confirm: > - Whether there was a recent change in the update package > - Whether the import issue is a known bug > - When a fix can be expected > > Thank you. I need information - build of windows, architecture, other software installed, and so forth. From Jason at zx2c4.com Sat Apr 18 16:23:52 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Sat, 18 Apr 2026 18:23:52 +0200 Subject: [ANNOUNCE] WireGuard for Windows and WireGuardNT, Version 1.0 Message-ID: Hey again, I?m happy to announce the v1.0 release of WireGuardNT and WireGuard for Windows. The final ?1.0 blockers? have been completed at last, and I?m quite happy to have reached this milestone. It should now be available from the built-in updater. And you can download it fresh from: - https://download.wireguard.com/windows-client/wireguard-installer.exe - https://www.wireguard.com/install/ And to learn more about each of these two Windows projects: - https://git.zx2c4.com/wireguard-windows/about/ - https://git.zx2c4.com/wireguard-nt/about/ Before I say more, I wanted to note that the WireGuard Project runs on support from large companies and individuals alike. You can help out at: https://www.wireguard.com/donations/ . If your company uses WireGuard, consider talking to your employer about becoming a large donor and appearing on that page. If you use a VPN from a VPN provider, consider writing to them to suggest they donate to the project. It does make a difference and is the reason the project is able to live on. The 1.0 release of WireGuardNT is a pile of bug fixes, after having done a big read through of the source code and countless hours of new testing. But it also has two big improvements, which have long been considered release blockers for me. Firstly, 1.0 now makes use of NdisWdfGetAdapterContextFromAdapterHandle(). WireGuard?s IOCTL works by piggybacking on the NDIS device node, so that it inherits NDIS? setup and permissions. Each IOCTL is thus passed through the device?s ?functional device object?. There?s no documented function to go from a pointer in the functional device object to the WireGuard-specific state allocated. The functional device object?s DeviceExtension field points to the NDIS_MINIPORT_BLOCK structure, which itself has a pointer to the WireGuard-specific state. But that latter pointer is at a potentially unstable offset, as it?s not within the documented part of NDIS_MINIPORT_BLOCK. So, previously, I was using the ?Reserved? member of the functional device object to stuff a pointer in, but who knows when that was to be used by something, a ticking time bomb. Fortunately, every Windows 10 version since the first one has the NdisWdfGetAdapterContextFromAdapterHandle() function, originally added for NetAdapterCx, which means it?s not going away any time soon and its behavior won?t change. This function simply goes to the right offset in NDIS_MINIPORT_BLOCK where the driver-specific state is stored. Put together, we get this handy function: static WG_DEVICE * WgDeviceFromFdo(_In_ DEVICE_OBJECT *DeviceObject) { if (DeviceObject->DeviceType != FILE_DEVICE_PHYSICAL_NETCARD || !DeviceObject->DeviceExtension) return NULL; return NdisWdfGetAdapterContextFromAdapterHandle(DeviceObject->DeviceExtension); } This seems to work well and will hopefully ensure reliability into the future. The second big 1.0 blocker that?s been solved is proper MTU change notifications. As you may or may not know, WireGuard pads packets to the nearest 16 bytes, but only up to the MTU of the interface, in order to protect against traffic analysis attacks. This means the WireGuard driver needs to know its own MTU. On Linux, we have full access to this information, as its considered a property of the network interface itself, so we can extract it trivially with `skb->dev->mtu`, and do various calculations. But on Windows, the MTU is a combined property of the network adapter?s minimum and maximum, the tcp/ip interface?s selected MTU, which splits into v4 and v6 cases, and the same split cases for the tcp/ip interface?s subinterfaces. This is sort of complicated, but I guess it fit a device model that at one point made sense. The driver is responsible for controlling the adapter?s minimum and maximum MTU. PowerShell?s Set-NetIpInterface will change the interface-level MTU (via SetIpInterfaceEntry()), while netsh.exe will change the subinterface-level MTU; both of these wind up affecting the other in subtle ways, and the net result is the same. Typically, the normal way of getting notifications about these changes, from userspace or from kernel space, is with NotifyIpInterfaceChange(), which calls a callback function with MibParameterNotification when something has changed. But, the callback never fires for MTU changes! That?s the only one missing. The struct the callback receives has a field for the MTU, but still, it?s never fired. Somebody on the relevant team at Microsoft told me in 2021, ?this is a plain oversight and should be fixed,? and somebody else mentioned backporting the fix to the 2019 release. But for whatever reason, this never happened, and now it?s 2026. In the interim period, I had a really horrific, but still stable, workaround: I started a thread, and every 3 seconds I called GetIpInterfaceEntry() on the LUID of every running WireGuard adapter. You heard that right? I just polled with a sleep. Gross dot net. But it was the only documented way of doing this! At the same time, I wrote a little program I could run on each new release of Windows to see at which point they fixed the bug, so that I could adjust the version check to avoid the poll loop on old versions. Unfortunately, the bug never got fixed. But I didn?t quite feel comfortable shipping a 1.0 with such a distasteful workaround. So I get to work? All userspace updates to the MTU go through a file called \Device\Nsi. The NSI driver is then responsible for dispatching this out to the various interfaces, and also keeping current with the various changes in the various interfaces. After attaching to \Device\Nsi using the standard NT filter-style pattern with IoAttachDeviceToDeviceStack(), I then intercept the IOCTL_NSI_SET_ALL_PARAMETERS message that I reverse engineered, looking at the NSI_SET_ALL_PARAMETERS struct, matching on object types NlInterfaceObject and NlSubInterfaceObject, and reading out the NlMTU parameter from NSI_IP_INTERFACE_RW and NSI_IP_SUBINTERFACE_RW. The parts of these structures we care about seem extremely stable. It appears to work well, and now the WireGuard driver can adapt to new MTU changes instantly, rather than within 3 seconds. And there?s no ugly polling loop. You can peruse this code in driver/nsi.c and driver/undocumented.h if you?re curious. That?s a lot of work ? it?s a whole separate .c file in the repo ? for just getting access to one value. But that?s how things go, and it?s information that simply must be had in order to implement WireGuard properly. Finally, there are a bunch of other little changes and fixes and now we compile in C23 mode, so we have access to the typeof() keyword. We also in theory could move to using alignas(n) instead of __declspec(align(n)), but C standard alignas() doesn?t work on types, only members of structs and on variables, which makes it sort of uglier to use. If you want a struct to always be aligned, then you put the alignas(n) on the first member. I find this awkward, so we?re sticking with __declspec(align(n)), which also seems pretty close to gcc?s __attribute__((aligned(n))) (which is how Linux defines its __aligned(n) macro). On the WireGuard for Windows front ? WireGuardNT, just discussed, is the bundled driver component of that ? there are 42 bug and correctness fixes of various varieties. And then there?s one nice improvement for older versions of Windows 10. Windows 10 1809 added support for SetInterfaceDnsSettings(), for setting the system DNS server programatically. Before that, the only documented way was to shell out to netsh.exe, which is what we did. It was pretty ugly, and the way of doing that involved some really gnarly parsing. Fortunately, newer Windows doesn?t need to do this. But it occurred to me ? since these older versions of Windows are essentially complete, I can just reverse engineer what netsh.exe is doing under the hood, and then do that myself, and not worry about that ever changing, since that?s only a fallback path used for these old Windows versions. It turns out to be pretty easy ? set two variables in a normal part of the registry and send ControlService(SERVICE_CONTROL_PARAMCHANGE) to the Dnscache service. Easy peasy. Anyway, please let me know how it goes and if you encounter any issues. Jason From Jason at zx2c4.com Mon Apr 20 10:40:21 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Mon, 20 Apr 2026 12:40:21 +0200 Subject: WireGuard Windows 0.6.1 - Timeline of issues (tunnels lost & import still broken) In-Reply-To: References: Message-ID: Fixed: https://git.zx2c4.com/wireguard-windows/commit/?id=857e549307fed893145bbab72ddd3fe08833c8c4 From syzbot+27a6e390f71f14f4fecf at syzkaller.appspotmail.com Mon Apr 27 09:11:36 2026 From: syzbot+27a6e390f71f14f4fecf at syzkaller.appspotmail.com (syzbot) Date: Mon, 27 Apr 2026 02:11:36 -0700 Subject: [syzbot] [wireguard?] BUG: soft lockup in wg_packet_decrypt_worker Message-ID: <69ef2848.170a0220.11de9.001b.GAE@google.com> Hello, syzbot found the following issue on: HEAD commit: 897d54018cc9 Merge tag 'fbdev-for-7.1-rc1-2' of git://git... git tree: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux master console output: https://syzkaller.appspot.com/x/log.txt?x=10470ff6580000 kernel config: https://syzkaller.appspot.com/x/.config?x=4e88e1f2f0b02f59 dashboard link: https://syzkaller.appspot.com/bug?extid=27a6e390f71f14f4fecf compiler: aarch64-linux-gnu-gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 userspace arch: arm Unfortunately, I don't have any reproducer for this issue yet. Downloadable assets: disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/fa3fbcfdac58/non_bootable_disk-897d5401.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/abfbe0527fdf/vmlinux-897d5401.xz kernel image: https://storage.googleapis.com/syzbot-assets/43fbdcd1dbf2/zImage-897d5401.xz IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+27a6e390f71f14f4fecf at syzkaller.appspotmail.com watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [kworker/1:3:20255] Modules linked in: irq event stamp: 104395 hardirqs last enabled at (104394): [] irqentry_exit_to_kernel_mode_after_preempt include/linux/irq-entry-common.h:515 [inline] hardirqs last enabled at (104394): [] arm64_exit_to_kernel_mode+0x50/0xc0 arch/arm64/kernel/entry-common.c:62 hardirqs last disabled at (104395): [] __el1_irq arch/arm64/kernel/entry-common.c:493 [inline] hardirqs last disabled at (104395): [] el1_interrupt+0x28/0x60 arch/arm64/kernel/entry-common.c:509 softirqs last enabled at (99688): [] spin_unlock_bh include/linux/spinlock.h:396 [inline] softirqs last enabled at (99688): [] ptr_ring_consume_bh include/linux/ptr_ring.h:377 [inline] softirqs last enabled at (99688): [] wg_packet_decrypt_worker+0x248/0x3a0 drivers/net/wireguard/receive.c:499 softirqs last disabled at (99692): [] spin_lock_bh include/linux/spinlock.h:348 [inline] softirqs last disabled at (99692): [] ptr_ring_consume_bh include/linux/ptr_ring.h:375 [inline] softirqs last disabled at (99692): [] wg_packet_decrypt_worker+0x68/0x3a0 drivers/net/wireguard/receive.c:499 CPU: 1 UID: 0 PID: 20255 Comm: kworker/1:3 Tainted: G L syzkaller #0 PREEMPT Tainted: [L]=SOFTLOCKUP Hardware name: linux,dummy-virt (DT) Workqueue: wg-crypt-wg0 wg_packet_decrypt_worker pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : memory_is_poisoned_n mm/kasan/generic.c:141 [inline] pc : memory_is_poisoned mm/kasan/generic.c:172 [inline] pc : check_region_inline mm/kasan/generic.c:191 [inline] pc : kasan_check_range+0x38/0x1b4 mm/kasan/generic.c:200 lr : __kasan_check_read+0x20/0x2c mm/kasan/shadow.c:31 sp : ffff8000a19478c0 x29: ffff8000a19478c0 x28: ffff80008766bed0 x27: 0000000000000000 x26: 1fffe00003374a09 x25: 1fffe00003374a0b x24: ffff000019ba5058 x23: 0000000000000000 x22: 1ffff00014328f20 x21: 1ffff00014328f3c x20: 0000000000000000 x19: ffff000019ba5048 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000001 x15: 0000000012224261 x14: 0000000000000001 x13: ffff800089e7c8d8 x12: ffff600003374a0a x11: 1fffe00003374a09 x10: ffff600003374a09 x9 : dfff800000000000 x8 : ffff000019ba5048 x7 : 0000000000000001 x6 : ffff600003374a09 x5 : ffff000019ba5048 x4 : ffff000000000000 x3 : ffff8000857fe9b0 x2 : 0000000000000000 x1 : 0000000000000001 x0 : 0000000000000001 Call trace: check_region_inline mm/kasan/generic.c:188 [inline] (P) kasan_check_range+0x38/0x1b4 mm/kasan/generic.c:200 (P) queued_spin_lock_slowpath+0x610/0xf80 kernel/locking/qspinlock.c:197 queued_spin_lock include/asm-generic/qspinlock.h:114 [inline] do_raw_spin_lock+0x258/0x308 kernel/locking/spinlock_debug.c:116 __raw_spin_lock_bh include/linux/spinlock_api_smp.h:151 [inline] _raw_spin_lock_bh+0x58/0x68 kernel/locking/spinlock.c:182 spin_lock_bh include/linux/spinlock.h:348 [inline] ptr_ring_consume_bh include/linux/ptr_ring.h:375 [inline] wg_packet_decrypt_worker+0x68/0x3a0 drivers/net/wireguard/receive.c:499 process_one_work+0x810/0x1b1c kernel/workqueue.c:3302 process_scheduled_works kernel/workqueue.c:3385 [inline] worker_thread+0x42c/0xc90 kernel/workqueue.c:3466 kthread+0x2f0/0x388 kernel/kthread.c:436 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:858 Sending NMI from CPU 1 to CPUs 0: NMI backtrace for cpu 0 CPU: 0 UID: 0 PID: 19280 Comm: kworker/0:7 Tainted: G L syzkaller #0 PREEMPT Tainted: [L]=SOFTLOCKUP Hardware name: linux,dummy-virt (DT) Workqueue: wg-crypt-wg0 wg_packet_decrypt_worker pstate: 10000005 (nzcV daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : __daif_local_irq_restore arch/arm64/include/asm/irqflags.h:176 [inline] pc : arch_local_irq_restore arch/arm64/include/asm/irqflags.h:195 [inline] pc : lock_release+0x39c/0x424 kernel/locking/lockdep.c:5892 lr : lockdep_recursion_finish kernel/locking/lockdep.c:470 [inline] lr : lock_release+0x37c/0x424 kernel/locking/lockdep.c:5891 sp : ffff8000a1eb7a40 x29: ffff8000a1eb7a50 x28: ffff00003f7678f0 x27: ffff000019ba50c0 x26: ffff600003374a19 x25: 1fffe00003374a18 x24: 0000000000000000 x23: ffff000012db5640 x22: ffff000012db61c0 x21: ffff8000828b6c88 x20: ffff000019ba5060 x19: ffff800087612208 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: ffff80008766f6e8 x14: 1ffff00010ecdedd x13: ffff800089e7c8d8 x12: ffff7000143d6f41 x11: 1ffff000143d6f40 x10: ffff7000143d6f40 x9 : dfff800000000000 x8 : 0000000000000003 x7 : 0000000000000001 x6 : 00000000000003e0 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 1fffe000025b6ac9 x2 : 0000000000000000 x1 : ffff7fffe29a8000 x0 : 00000000000000c0 Call trace: __daif_local_irq_restore arch/arm64/include/asm/irqflags.h:175 [inline] (P) arch_local_irq_restore arch/arm64/include/asm/irqflags.h:195 [inline] (P) lock_release+0x39c/0x424 kernel/locking/lockdep.c:5892 (P) __raw_spin_unlock_bh include/linux/spinlock_api_smp.h:194 [inline] _raw_spin_unlock_bh+0x28/0x54 kernel/locking/spinlock.c:214 spin_unlock_bh include/linux/spinlock.h:396 [inline] ptr_ring_consume_bh include/linux/ptr_ring.h:377 [inline] wg_packet_decrypt_worker+0x13c/0x3a0 drivers/net/wireguard/receive.c:499 process_one_work+0x810/0x1b1c kernel/workqueue.c:3302 process_scheduled_works kernel/workqueue.c:3385 [inline] worker_thread+0x42c/0xc90 kernel/workqueue.c:3466 kthread+0x2f0/0x388 kernel/kthread.c:436 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:858 BUG: workqueue lockup - pool cpus=0 node=0 flags=0x0 nice=0 stuck for 33s! Showing busy workqueues and worker pools: workqueue events: flags=0x100 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=4 refcnt=5 pending: nsim_dev_hwstats_traffic_work, 2*psi_avgs_work, vmstat_shepherd pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=10 refcnt=11 pending: 9*nsim_dev_hwstats_traffic_work, psi_avgs_work workqueue events_unbound: flags=0x2 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 in-flight: 16479:call_usermodehelper_exec_work for 42s workqueue events_unbound: flags=0x2 pwq 8: cpus=0-1 flags=0x4 nice=0 active=5 refcnt=6 pending: 5*nsim_dev_trap_report_work pwq 8: cpus=0-1 flags=0x4 nice=0 active=5 refcnt=6 pending: 5*nsim_dev_trap_report_work workqueue events_power_efficient: flags=0x182 pwq 8: cpus=0-1 flags=0x4 nice=0 active=2 refcnt=3 pending: neigh_managed_work, wg_ratelimiter_gc_entries pwq 8: cpus=0-1 flags=0x4 nice=0 active=4 refcnt=5 pending: neigh_periodic_work, gc_worker, neigh_periodic_work, neigh_managed_work workqueue mm_percpu_wq: flags=0x108 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: vmstat_update pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: vmstat_update workqueue writeback: flags=0x4a pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 in-flight: 10400:wb_workfn for 33s workqueue kblockd: flags=0x118 pwq 7: cpus=1 node=0 flags=0x0 nice=-20 active=2 refcnt=3 pending: blk_mq_timeout_work, blk_mq_requeue_work workqueue ipv6_addrconf: flags=0x6000a pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=6 pending: addrconf_verify_work inactive: 2*addrconf_verify_work workqueue wg-kex-wg0: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-crypt-wg0: flags=0x128 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 in-flight: 19280:wg_packet_decrypt_worker for 33s pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=2 refcnt=3 in-flight: 20255:wg_packet_decrypt_worker for 33s pending: wg_packet_encrypt_worker workqueue wg-crypt-wg1: flags=0x128 pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue wg-kex-wg2: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-crypt-wg2: flags=0x128 pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue wg-kex-wg0: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-kex-wg1: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-kex-wg2: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=2 refcnt=3 pending: 2*wg_packet_handshake_send_worker workqueue wg-kex-wg0: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=3 refcnt=4 in-flight: 15424:wg_packet_handshake_send_worker for 33s ,20263:wg_packet_handshake_send_worker for 33s pending: wg_packet_handshake_send_worker workqueue wg-kex-wg1: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-kex-wg2: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker pwq 8: cpus=0-1 flags=0x4 nice=0 active=2 refcnt=3 in-flight: 17220:wg_packet_handshake_send_worker for 33s pending: wg_packet_handshake_send_worker workqueue wg-kex-wg0: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-crypt-wg0: flags=0x128 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_decrypt_worker pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue wg-kex-wg1: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-crypt-wg1: flags=0x128 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue wg-kex-wg2: flags=0x6 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=2 pending: wg_packet_handshake_send_worker workqueue wg-crypt-wg2: flags=0x128 pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue wg-crypt-wg0: flags=0x128 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=2 refcnt=3 pending: wg_packet_decrypt_worker, wg_packet_encrypt_worker workqueue wg-crypt-wg1: flags=0x128 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue wg-crypt-wg2: flags=0x128 pwq 2: cpus=0 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker pwq 6: cpus=1 node=0 flags=0x0 nice=0 active=1 refcnt=2 pending: wg_packet_encrypt_worker workqueue krds_cp_wq#1/0: flags=0x20002 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=4 pending: rds_connect_worker workqueue krds_cp_wq#2/0: flags=0x20002 pwq 8: cpus=0-1 flags=0x4 nice=0 active=1 refcnt=4 pending: rds_connect_worker pool 2: cpus=0 node=0 flags=0x0 nice=0 hung=33s workers=7 idle: 20317 20625 17368 18803 20184 16642 pool 6: cpus=1 node=0 flags=0x0 nice=0 hung=33s workers=6 idle: 20316 15747 16513 18710 19225 pool 8: cpus=0-1 flags=0x4 nice=0 hung=0s workers=13 idle: 15591 8052 14588 7215 11940 15432 19121 Showing backtraces of busy workers in stalled worker pools: pool 2: task:kworker/0:7 state:R running task stack:0 pid:19280 tgid:19280 ppid:2 task_flags:0x4208060 flags:0x00000012 Workqueue: wg-crypt-wg0 wg_packet_decrypt_worker Call trace: show_stack+0x18/0x24 arch/arm64/kernel/stacktrace.c:499 (C) sched_show_task kernel/sched/core.c:8139 [inline] sched_show_task+0x454/0x5e0 kernel/sched/core.c:8114 show_cpu_pool_busy_workers kernel/workqueue.c:7674 [inline] show_cpu_pools_busy_workers kernel/workqueue.c:7693 [inline] wq_watchdog_timer_fn+0x840/0x870 kernel/workqueue.c:7809 call_timer_fn+0x1b8/0xaa0 kernel/time/timer.c:1748 expire_timers kernel/time/timer.c:1799 [inline] __run_timers+0x8bc/0xb30 kernel/time/timer.c:2374 __run_timer_base kernel/time/timer.c:2386 [inline] __run_timer_base kernel/time/timer.c:2378 [inline] run_timer_base+0x110/0x180 kernel/time/timer.c:2395 run_timer_softirq+0x24/0x50 kernel/time/timer.c:2406 handle_softirqs+0x2dc/0x1050 kernel/softirq.c:622 __do_softirq+0x14/0x20 kernel/softirq.c:656 ____do_softirq+0x10/0x20 arch/arm64/kernel/irq.c:68 call_on_irq_stack+0x30/0x48 arch/arm64/kernel/entry.S:889 do_softirq_own_stack+0x1c/0x40 arch/arm64/kernel/irq.c:73 do_softirq kernel/softirq.c:523 [inline] do_softirq+0x12c/0x15c kernel/softirq.c:510 __local_bh_enable_ip+0x408/0x4a0 kernel/softirq.c:450 __raw_spin_unlock_bh include/linux/spinlock_api_smp.h:196 [inline] _raw_spin_unlock_bh+0x44/0x54 kernel/locking/spinlock.c:214 spin_unlock_bh include/linux/spinlock.h:396 [inline] ptr_ring_consume_bh include/linux/ptr_ring.h:377 [inline] wg_packet_decrypt_worker+0x13c/0x3a0 drivers/net/wireguard/receive.c:499 process_one_work+0x810/0x1b1c kernel/workqueue.c:3302 process_scheduled_works kernel/workqueue.c:3385 [inline] worker_thread+0x42c/0xc90 kernel/workqueue.c:3466 kthread+0x2f0/0x388 kernel/kthread.c:436 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:858 --- This report is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. syzbot will keep track of this issue. See: https://goo.gl/tpsmEJ#status for how to communicate with syzbot. If the report is already addressed, let syzbot know by replying with: #syz fix: exact-commit-title If you want to overwrite report's subsystems, reply with: #syz set subsystems: new-subsystem (See the list of subsystem names on the web dashboard) If the report is a duplicate of another one, reply with: #syz dup: exact-subject-of-another-report If you want to undo deduplication, reply with: #syz undup From free122448 at hotmail.com Wed Apr 22 11:32:22 2026 From: free122448 at hotmail.com (Ian Chen) Date: Wed, 22 Apr 2026 11:32:22 -0000 Subject: WireGuard obfuscation & active probing: staying virtuous under pressure In-Reply-To: References: Message-ID: > WireGuard over Shadowsocks-2022 > =============================== > > TL;DR: Too much crypto + deployment challenges. > > Shadowsocks is a good solution against censor, but it strips 40 more > bytes from MTU and AEADs data twice: XChaCha20-Poly1305 of > Shadowsocks + > ChaCha20-Poly1305 of WireGuard burning twice as much carbon credits. > Performance matters: e.g. Mullvad introduces LWO claiming performance > improvement over Shadowsocks. I developed swgp-go around the same time I wrote the spec for Shadowsocks 2022. At the time, I intentionally left replay protection out of swgp-go, because I thought WireGuard wouldn't need it. Thanks to your work, I now understand that this assumption was wrong! So I added it into swgp-go: https://github.com/database64128/swgp-go/commit/207a055ab0a1058579f299fc1021cc64c95b21db The new "zero-overhead-2026" and "paranoid-2026" modes provide replay protection for handshake packets. Replayed packets are dropped by checking the nonce and an encrypted unix epoch timestamp, similar to how Shadowsocks 2022's TCP construction does it. This won't address the "DoSer" scenario, but should provide enough protection against censors without knowledge of the OBFSK. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: This is a digitally signed message part URL: From justin.t.ho at gmail.com Fri Apr 24 03:19:27 2026 From: justin.t.ho at gmail.com (Justin) Date: Fri, 24 Apr 2026 03:19:27 -0000 Subject: Unable to use wireguard 0.6 / 1.0 / 1.0.1 on Windows 24H2 Message-ID: I've been using 0.5.3 for a long time. I upgraded to 0.6/1.0/1.0.1 and haven't been able to connect. The install appeared to succeed. I've uninstalled, rebooted, and reinstalled 0.5.3 and it works fine. It seems the kernel driver is not installing for me. What logs would be useful? I've attached some that I could find. Let me know if I can provide additional information. In case it matters: I run as a regular user, and I open tunnels by starting them in an elevated command prompt. -- --- Justin Ho -------------- next part -------------- Get-Content "$env:windir\inf\setupapi.dev.log" | Select-String -Pattern "wireguard|wintun|fffff" -Context 2,5 | Select-Object -Last 30 > idb: {Register Driver Package: C:\Windows\System32\DriverStore\FileRepository\wireguard.inf_amd64_053a7fe4b9f21442\wireguard.inf} 19:50:32.534 > idb: Created driver package object 'wireguard.inf_amd64_053a7fe4b9f21442' in DRIVERS database node. idb: Created driver INF file object 'oem36.inf' in DRIVERS database node. > idb: Registered driver package 'wireguard.inf_amd64_053a7fe4b9f21442' with 'oem36.inf'. idb: {Register Driver Package: exit(0x00000000)} 19:50:32.538 > idb: {Publish Driver Package: C:\Windows\System32\DriverStore\FileRepository\wireguard.inf_amd64_053a7fe4b9f21442\wireguard.inf} 19:50:32.539 > idb: Activating driver package 'wireguard.inf_amd64_053a7fe4b9f21442'. > cpy: Published 'wireguard.inf_amd64_053a7fe4b9f21442\wireguard.inf' to 'oem36.inf'. > idb: Indexed 2 device IDs for 'wireguard.inf_amd64_053a7fe4b9f21442'. sto: Flushed driver database node 'DRIVERS'. Time = 0 ms sto: Flushed driver database node 'SYSTEM'. Time = 0 ms idb: {Publish Driver Package: exit(0x00000000)} 19:50:32.548 sto: {DRIVERSTORE IMPORT END} 19:50:32.550 dvi: Flushed all driver package files to disk. Time = 1 ms > sig: Installed catalog 'wireguard.cat' as 'oem36.cat'. sto: {DRIVERSTORE IMPORT END: exit(0x00000000)} 19:50:32.606 sto: {Core Driver Package Import: exit(0x00000000)} 19:50:32.607 sto: {Stage Driver Package: exit(0x00000000)} 19:50:32.608 > ! dvi: Unable to locate device 'ROOT\WIREGUARD\0000'. cr = 0x0D sto: {Setup Import Driver Package - exit (0x00000000)} 19:50:32.735 > inf: Driver Store Path: C:\Windows\System32\DriverStore\FileRepository\wireguard.inf_amd64_053a7fe4b9f21442\wireguard.inf inf: Published Inf Path: C:\Windows\INF\oem36.inf <<< Section end 2026/04/23 19:50:32.778 <<< [Exit status: SUCCESS] > >>> [Device Install (Hardware initiated) - SWD\WireGuard\{06A6F956-B04C-FB24-8D43-BCF8C102B460}] >>> Section start 2026/04/23 19:50:32.807 ump: Install needed due to device having problem code CM_PROB_REINSTALL > utl: {Select Drivers - SWD\WireGuard\{06A6F956-B04C-FB24-8D43-BCF8C102B460}} 19:50:32.815 utl: Driver Node: utl: Status - Selected > utl: Driver INF - oem36.inf (C:\Windows\System32\DriverStore\FileRepository\wireguard.inf_amd64_053a7fe4b9f21442\wireguard.inf) utl: Class GUID - {4d36e972-e325-11ce-bfc1-08002be10318} utl: Driver Version - 04/18/2026,1.0.0.0 > utl: Configuration - WireGuard utl: Driver Rank - 00FF0000 utl: Signer Score - WHQL (0D000005) utl: Submission ID - 58177670_13751989183616671_1152921505700876788 utl: Attributes - Universal utl: {Select Drivers - exit(0x00000000} 19:50:32.822 dvi: Install flags: 0x00010000 dvi: {Core Device Install} 19:50:32.825 > dvi: {Configure Device - SWD\WireGuard\{06A6F956-B04C-FB24-8D43-BCF8C102B460}} 19:50:32.826 dvi: Device Status: 0x01802400 [0x12 - 0xc0000493] dvi: Config Flags: 0x00000000 dvi: Parent Device: HTREE\ROOT\0 > sto: {Configure Driver Package: C:\Windows\System32\DriverStore\FileRepository\wireguard.inf_amd64_053a7fe4b9f21442\wireguard.inf} 19:50:32.829 > sto: Source Filter = WireGuard inf: Config Options = IsolationCompat inf: Class GUID = {4d36e972-e325-11ce-bfc1-08002be10318} inf: Class Options = Configurable > inf: {Configure Driver: WireGuard Tunnel} > inf: Section Name = WireGuard.Install > inf: {Add Service: WireGuard} inf: Flags = 0x2 inf: Start Type = 3 inf: Service Type = 1 inf: Error Control = 1 > inf: Image Path = \SystemRoot\System32\drivers\wireguard.sys > inf: Display Name = WireGuard > inf: Description = WireGuard Tunnel > inf: Updated service 'WireGuard'. inf: {Add Service: exit(0x00000000)} > inf: Hardware Id = WireGuard > inf: {Configure Driver Configuration: WireGuard.Install} > inf: Service Name = WireGuard inf: Config Flags = 0x00000000 inf: {Configure Driver Configuration: exit(0x00000000)} inf: {Configure Driver: exit(0x00000000)} flq: {FILE_QUEUE_COMMIT} 19:50:32.848 !!! bak: Failed to create temp file under 'C:\Windows\Temp'. Error = 0x00000570 > ! cpy: Unable to backup file 'C:\Windows\System32\drivers\wireguard.sys'. Error = 0x00000570 !!! flq: Failed to commit copy queue. Error = 0x000003e3 !!! flq: FileQueueCommit aborting !!! flq: Error 995: The I/O operation has been aborted because of either a thread exit or an application request. flq: {FILE_QUEUE_COMMIT - exit(0x000003e3)} 19:50:32.852 !!! sto: Failed to configure driver package. Error = 0x000003E3 ! dvi: Unable to configure device, falling back to standard device installation. dvi: Searching for hardware ID(s): > dvi: wireguard dvi: Searching for compatible ID(s): dvi: swd\generic dvi: Class GUID of device changed to: {4d36e972-e325-11ce-bfc1-08002be10318}. ndv: {Core Device Install} 19:50:32.866 > dvi: {Install Device - SWD\WIREGUARD\{06A6F956-B04C-FB24-8D43-BCF8C102B460}} 19:50:32.867 dvi: Device Status: 0x01802400 [0x12 - 0xc0000493] dvi: Config Flags: 0x00000000 dvi: Parent Device: HTREE\ROOT\0 dvi: {DIF_ALLOW_INSTALL} 19:50:32.870 dvi: Default installer: Enter 19:50:32.871 -------------- next part -------------- 2026-04-23 17:08:18.943111: [MGR] Starting WireGuard/1.0.1 (Windows 10.0.26100; amd64) 2026-04-23 17:08:49.676728: [TUN] [redacted] Starting WireGuard/1.0.1 (Windows 10.0.26100; amd64) 2026-04-23 17:08:49.676728: [TUN] [redacted] Watching network interfaces 2026-04-23 17:08:49.678331: [TUN] [redacted] Resolving DNS names 2026-04-23 17:08:49.685827: [TUN] [redacted] Creating network adapter 2026-04-23 17:08:49.854975: [TUN] [redacted] Installing driver 1.0 2026-04-23 17:08:49.855756: [TUN] [redacted] Extracting driver 2026-04-23 17:08:49.856819: [TUN] [redacted] Installing driver 2026-04-23 17:08:50.317910: [TUN] [redacted] Creating adapter 2026-04-23 17:09:05.335011: [TUN] [redacted] Timed out waiting for device query: The wait operation timed out. (Code 0x00000102) 2026-04-23 17:09:05.335544: [TUN] [redacted] Failed to setup adapter (problem code: 0x12, ntstatus: 0xC0000493): The property set specified does not exist on the object. (Code 0x00000492) 2026-04-23 17:09:05.409463: [TUN] [redacted] Unable to create network adapter: Error creating adapter: The property set specified does not exist on the object. 2026-04-23 17:09:05.409969: [TUN] [redacted] Shutting down 2026-04-23 17:10:10.303316: [TUN] [redacted] Starting WireGuard/1.0.1 (Windows 10.0.26100; amd64) 2026-04-23 17:10:10.303316: [TUN] [redacted] Watching network interfaces 2026-04-23 17:10:10.304997: [TUN] [redacted] Resolving DNS names 2026-04-23 17:10:10.311380: [TUN] [redacted] Creating network adapter 2026-04-23 17:10:10.358084: [TUN] [redacted] Using existing driver 1.0 2026-04-23 17:10:10.372308: [TUN] [redacted] Creating adapter 2026-04-23 17:10:25.387161: [TUN] [redacted] Timed out waiting for device query: The wait operation timed out. (Code 0x00000102) 2026-04-23 17:10:25.387580: [TUN] [redacted] Failed to setup adapter (problem code: 0x12, ntstatus: 0xC0000493): The property set specified does not exist on the object. (Code 0x00000492) 2026-04-23 17:10:25.457324: [TUN] [redacted] Unable to create network adapter: Error creating adapter: The property set specified does not exist on the object. 2026-04-23 17:10:25.457324: [TUN] [redacted] Shutting down From rfrohl at suse.com Fri Apr 24 09:33:56 2026 From: rfrohl at suse.com (Robert Frohl) Date: Fri, 24 Apr 2026 09:33:56 -0000 Subject: [PATCH] Revert "dns-hatchet: apply resolv.conf's selinux context to new resolv.conf" Message-ID: <20260424093340.42034-1-rfrohl@suse.com> This reverts commit 2ce4680bd34f371aacd3c09673c3c907274321cd. selinux does not allow every domain to set file contexts and will raise relabelto/relabelfrom AVCs and block these changes if a domain tries to update the selinux context. It is better to ignore selinux and leave the proper labeling to the selinux policy, which can add proper file transitions for the right context. This also allows for a cleaner change in the selinux policy, because otherwise it will need infrastructure to hide the relabel AVCs as well. For reference please see the selinux policy PR: https://github.com/fedora-selinux/selinux-policy/pull/3030 Signed-off-by: Robert Frohl --- contrib/dns-hatchet/hatchet.bash | 2 -- 1 file changed, 2 deletions(-) diff --git a/contrib/dns-hatchet/hatchet.bash b/contrib/dns-hatchet/hatchet.bash index bc4d090..6f167cc 100644 --- a/contrib/dns-hatchet/hatchet.bash +++ b/contrib/dns-hatchet/hatchet.bash @@ -20,11 +20,9 @@ set_dns() { [[ ${#DNS_SEARCH[@]} -eq 0 ]] || printf 'search %s\n' "${DNS_SEARCH[*]}" } | unshare -m --propagation shared bash -c "$(cat <<-_EOF set -e - context="\$(stat -c %C /etc/resolv.conf 2>/dev/null)" || unset context mount --make-private /dev/shm mount -t tmpfs none /dev/shm cat > /dev/shm/resolv.conf - [[ -z \$context || \$context == "?" ]] || chcon "\$context" /dev/shm/resolv.conf 2>/dev/null || true mount -o remount,ro /dev/shm mount -o bind,ro /dev/shm/resolv.conf /etc/resolv.conf _EOF -- 2.53.0 From free122448 at hotmail.com Sun Apr 26 04:50:46 2026 From: free122448 at hotmail.com (Ian Chen) Date: Sun, 26 Apr 2026 12:50:46 +0800 Subject: WireGuard obfuscation & active probing: staying virtuous under pressure In-Reply-To: <1fa035ae8cbcf09df9bd196228f5a3d6cc1a6faa.camel@hotmail.com> References: <1fa035ae8cbcf09df9bd196228f5a3d6cc1a6faa.camel@hotmail.com> Message-ID: On Wed, 2026-04-22 at 19:32 +0800, Ian Chen wrote: > > WireGuard over Shadowsocks-2022 > > =============================== > > > > TL;DR: Too much crypto + deployment challenges. > > > > Shadowsocks is a good solution against censor, but it strips 40 > > more > > bytes from MTU and AEADs data twice: XChaCha20-Poly1305 of > > Shadowsocks + > > ChaCha20-Poly1305 of WireGuard burning twice as much carbon > > credits. > > Performance matters: e.g. Mullvad introduces LWO claiming > > performance > > improvement over Shadowsocks. > > I developed swgp-go around the same time I wrote the spec for > Shadowsocks 2022. At the time, I intentionally left replay protection > out of swgp-go, because I thought WireGuard wouldn't need it. > > Thanks to your work, I now understand that this assumption was wrong! > So I added it into swgp-go: > https://github.com/database64128/swgp-go/commit/207a055ab0a1058579f299fc1021cc64c95b21db > > The new "zero-overhead-2026" and "paranoid-2026" modes provide replay > protection for handshake packets. Replayed packets are dropped by > checking the nonce and an encrypted unix epoch timestamp, similar to > how Shadowsocks 2022's TCP construction does it. > > This won't address the "DoSer" scenario, but should provide enough > protection against censors without knowledge of the OBFSK. I sent the previous email a few days ago, and it never showed up on the mailing list archive, probably due to all that PGP signing stuff I didn't turn off. Let's see if this one works.