import { Callout } from 'nextra/components';
import { Steps } from 'nextra/components';
import { Tabs } from 'nextra/components';
import { MyTab } from 'components/generic-tabs.tsx';
import { AccordionTemplate } from 'components/accordion-template.tsx';
import NTMExplanation from 'components/operators/snippets/ntm-accordion-explanation.mdx';

## Security Patch: `CopyFail` & `DirtyFrag`

In spring 2026 two critical Linux kernel vulnerabilities had been disclosed. Both allow any local user or process to gain root access on the machine - no special permissions needed.

<Callout type="warning" emoji="⚠️">
**What is exposed?** An attacker (or any compromised process) can take full control of the machine: read or exfiltrate everything, modify files, install backdoors, or escape containers onto the host.
</Callout>

**Security patch required! Follow these steps to patch the vulnerability as soon as possible!**

**CVEs covered**

| CVE | Name | Affected module |
|---|---|---|
| `CVE-2026-31431` | `CopyFail` | `algif_aead` |
| `CVE-2026-43284` | `DirtyFrag` | `esp4`, `esp6` |
| `CVE-2026-43500` | `DirtyFrag` | `rxrpc` |

<div>
  <Tabs items={[
    <strong>Directly on the hosting server</strong>,
    <strong>Using Ansible</strong>,
    ]} defaultIndex="0">
    <MyTab>
      <Steps>

<Callout type="warning" emoji="⚠️">
**This guide is written from root perspective, please add `sudo` to your commands if you are non-root user.**
</Callout>

###### 1. Check if mitigations are already applied

Many hosting providers already applied these mitigations automatically via `unattended-upgrades`. Run these checks first:

```sh
cat /etc/modprobe.d/disable-algif_aead.conf 2>/dev/null && echo "Already mitigated" || echo "Not yet mitigated"
cat /etc/modprobe.d/dirtyfrag.conf 2>/dev/null && echo "Already mitigated" || echo "Not yet mitigated"
```

Compare your output to this table:

| Check | Safe output | Action if not safe |
|---|---|---|
| `disable-algif_aead.conf` | `Already mitigated` | Go to [Step 2](#2-apply-the-interim-mitigation---disable-algif_aead) |
| `dirtyfrag.conf` | `Already mitigated` | Go to [Step 3](#3-apply-the-interim-mitigation---disable-esp4-esp6-and-rxrpc) |

If both checks are `Already mitigated` - **you are done, no further action needed.**


###### 2. Apply the interim mitigation - disable `algif_aead`

The fastest fix on Debian/Ubuntu is to update the `kmod` package - this is how [providers applied it](https://ubuntu.com/blog/copy-fail-vulnerability-fixes-available) automatically and avoids a reboot:

```sh
apt update && apt install --only-upgrade kmod
rmmod algif_aead 2>/dev/null || true
```

- Alternatively, apply manually:

```sh
echo "install algif_aead /bin/false" | tee /etc/modprobe.d/disable-algif_aead.conf
rmmod algif_aead 2>/dev/null || true
```

- Drop page cache to clear any contamination:

```sh
echo 3 > /proc/sys/vm/drop_caches
```

<Callout type="info" emoji="ℹ️">
No reboot is required unless the module was already in active use by a running process. The `rmmod` command above unloads it live.
</Callout>

<Callout type="warning" emoji="⚠️">
**RHEL, AlmaLinux, Rocky, CentOS** only: this module is baked into the kernel on these distros - the command above does nothing. You must wait for a patched kernel from your distro and apply it when available.
</Callout>

Continue to [Step 4](#4-restore-gateway-egress-routing--wireguard-functionality).

###### 3. Apply the interim mitigation - disable `esp4`, `esp6`, and `rxrpc`

```sh
sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf"
rmmod esp4 esp6 rxrpc 2>/dev/null || true
```

- Drop page cache to clear any contamination:

```sh
echo 3 > /proc/sys/vm/drop_caches
```

Continue to [Step 4](#4-restore-gateway-egress-routing--wireguard-functionality).

###### 4. Restore Gateway egress routing & WireGuard functionality

<Callout type="warning" emoji="⚠️">
This step applies only to Gateway nodes. Skip this step for Mixnodes.
</Callout>

If your server was rebooted for any reason, all iptables rules including NAT, forwarding rules, and the `NYM-EXIT` chain are dropped. Unless `iptables-persistent` was already configured, these rules are gone.

- Run the [Nym network tunnel manager](https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/network-tunnel-manager.sh) (NTM) to restore and persist everything. NTM will also install `iptables-persistent` if not already present, ensuring rules survive future reboots:

```sh
curl -L "https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/network-tunnel-manager.sh" -o network-tunnel-manager.sh
```

- Run NTM (Standard SSH on port 22 (default)):
```sh
chmod +x ./network-tunnel-manager.sh && 
./network-tunnel-manager.sh complete_networking_configuration
```

- NTM on non-standart SSH port (replace `2222` with your actual port):
```sh
chmod +x ./network-tunnel-manager.sh && 
HOST_SSH_PORT=2222 ./network-tunnel-manager.sh complete_networking_configuration
```

<NTMExplanation />

###### 5. Verify egress routing & WireGuard functionality

There are a few ways to check that your WireGuard is working correctly:

- Connect to your node in NymVPN as an exit node in the *Fast* mode, if you rebooted it may take up to one hour for the node to be working properly again

- Verify WireGuard handshakes are resuming inside the node:

```sh
watch -n 5 'wg show all | grep -E "peer|latest handshake|transfer"'
```

Within 60–90 seconds you should see `latest handshake: X seconds ago` timestamps appearing next to active peers and transfer bytes incrementing. Press `Ctrl+C` to exit the watch loop.
      </Steps>
    </MyTab>
    <MyTab>

If you are using Ansible you can use this playbook [mitigate_kernel_CVE.yml](https://github.com/nymtech/nym/tree/develop/ansible/nym-node/playbooks/mitigate_kernel_CVE.yml).

      <Steps>
###### 1. Create new playbook

- Navigate to your Nym node Ansible directory with all playbooks (`/playbooks`)

- You can double check that you are in the right place, running `ls` command and checking this output:

<AccordionTemplate name="Command output">
```
ansible.cfg  bond.yml  deploy.yml  group_vars  inventory  system-maintenance.yml  upgrade.yml
```
</AccordionTemplate>
- Download the playbook
```sh
curl -o mitigate_kernel_CVE.yml -L https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/ansible/nym-node/playbooks/mitigate_kernel_CVE.yml
```
- To control, run `ls` again
<AccordionTemplate name="Command output">
```
ansible.cfg  bond.yml  deploy.yml  group_vars  inventory  mitigate_kernel_CVE.yml  system-maintenance.yml  upgrade.yml
```
</AccordionTemplate>

###### 2. Run playbook `mitigate_kernel_CVE.yml`

- For safety start only with one node:
```sh
ansible-playbook mitigate_kernel_CVE.yml -l node1
```

- Check if everything worked smooth on the node machine

- Run on all machines in your inventory
```sh
ansible-playbook mitigate_kernel_CVE.yml
```

###### 3. Ensure routing & WireGuard functionality

<Callout type="warning" emoji="⚠️">
This step applies only to Gateway nodes. Skip this step for Mixnodes.
</Callout>

In case your hosting servers rebooted all iptables rules including NAT, forwarding rules, and the `NYM-EXIT` chain, are dropped. Unless `iptables-persistent` was already configured before the reboot, these rules are gone. 

- Run the [Nym network tunnel manager](https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/network-tunnel-manager.sh) (NTM) to restore and persist everything, using Ansible playbook `deploy.yml` pointing to the correct role:

- For safety start only with one node:
```sh
ansible-playbook deploy.yml -t ntm -l node1
```

- Check if everything worked smooth on the node machine

- Run on all machines in your inventory
```sh
ansible-playbook deploy.yml -t ntm
```

###### 4. Verify egress routing & WireGuard functionality

- Connect to your node in NymVPN as an exit node in the *Fast* mode, it may take up to one hour for the node to be working properly again

In case something doesn't work fine, please check the manual steps and [troubleshooting steps](#troubleshooting-wireguard-handshake-fails-after-patching) below

      </Steps>
    </MyTab>
  </Tabs>
</div>

### Troubleshooting: WireGuard handshake fails after patching

If after completing all steps above WireGuard peers are still not handshaking and you can't connect to your node via NymVPN, work through this checklist:

<Steps>

###### 1. Confirm blacklists are in place

```sh
cat /etc/modprobe.d/disable-algif_aead.conf 2>/dev/null && echo "algif_aead: mitigated" || echo "algif_aead: NOT mitigated"
cat /etc/modprobe.d/dirtyfrag.conf 2>/dev/null && echo "dirtyfrag: mitigated" || echo "dirtyfrag: NOT mitigated"
```

- Both files must exist - these are what prevent the modules from loading on demand or after reboot

- If either is missing, return to [Step 2](#2-apply-the-interim-mitigation---disable-algif_aead) or [Step 3](#3-apply-the-interim-mitigation---disable-esp4-esp6-and-rxrpc) and apply the missing mitigation

###### 2. Check for stale xfrm state

```sh
ip xfrm policy list && ip xfrm state list
```

- If either returns entries, flush them — WireGuard does not use xfrm and stale entries can intercept handshake packets:

```sh
ip xfrm state flush && ip xfrm policy flush
```

###### 3. Confirm the `nymwg` interface is up

```sh
ip addr show type wireguard
```
- If absent, restart the `nym-node service`: 

```sh
systemctl restart nym-node
```

###### 4. Check iptables forwarding rules are present

```sh
iptables -L FORWARD -n -v | grep -E 'nymwg|nymtun'
iptables -L NYM-EXIT -n | head -10
```

- If the `NYM-EXIT` chain is missing or `FORWARD` has no entries for `nymwg`, re-run [Step 4](#4-restore-gateway-egress-routing--wireguard-functionality).

###### 5. Confirm IP forwarding is enabled

```sh
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding
```

- Both should return `= 1`. If not: `sysctl -w net.ipv4.ip_forward=1 && sysctl -w net.ipv6.conf.all.forwarding=1`

###### 6. Watch for live handshake packets

- Install tcpdump if missing

```sh
apt install tcpdump -y           # Debian/Ubuntu
dnf install tcpdump -y           # RHEL family

# replace with your actual WG port from: ss -ulnp | grep nym-node
tcpdump -ni any udp port 51264  
```

Trigger a connection attempt from a client. If you see packets arriving but WireGuard is not responding, check `journalctl -u nym-node -n 100` for errors from the binary itself.

</Steps>