> ## Documentation Index
> Fetch the complete documentation index at: https://wireblast.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Transmit and receive

> Why Wireblast only transmits by default, and how to turn receiving on without cutting off your own SSH session.

Wireblast transmits only, unless you tell it otherwise. This is the most important safety decision in the tool, and it's worth understanding rather than working around.

## Why receiving is opt-in

An XDP program sits in front of the kernel. Whatever it claims, the kernel never sees.

That's fine when the program claims nothing, which is the default. Wireblast installs a filter that matches nothing at all, so every packet the interface receives continues up the normal stack. Your SSH session, DNS, ARP, monitoring, everything: untouched.

Turn receiving on and packets start getting pulled aside. Do that too broadly on a box you're logged into over that interface, and you cut yourself off. Not "the tool gets slow" but the session freezes, and stays frozen until the run ends.

So receiving is something you ask for, per run, and Wireblast tells you exactly what you're about to take:

```mermaid theme={null}
flowchart TD
    P([Packet arrives on the NIC]) --> X{Does it match<br/>the receive filter?}
    X -->|"--rx-mode none<br/>(the default: nothing matches)"| K[Kernel network stack<br/>SSH, DNS, ARP, your apps]
    X -->|no| K
    X -->|yes| W[AF_XDP socket<br/>Wireblast counts it]
    W --> G([The kernel never sees it])
```

## The receive modes

| `--rx-mode`       | What it takes                                                            | Needs                                         |
| ----------------- | ------------------------------------------------------------------------ | --------------------------------------------- |
| `none`            | Nothing. Transmit-only. **Default.**                                     |                                               |
| `generated-flow`  | Return traffic for the flows this run generates                          | a source IP, and an IP-based pattern          |
| `udp-port`        | IPv4 UDP packets to specific destination ports                           | `--rx-port`                                   |
| `tcp-port`        | IPv4 TCP packets to specific destination ports                           | `--rx-port`                                   |
| `cidr`            | Everything from a source address range (IPv4 or IPv6)                    | `--rx-cidr`                                   |
| `keep-management` | Everything **except** SSH and DNS to and from this box (plus ARP and ND) | nothing                                       |
| `all`             | **Every packet on the interface**                                        | `--allow-match-all` plus a typed confirmation |

Before it attaches anything, Wireblast spells out the consequence in plain language:

<CodeGroup>
  ```text --rx-mode none theme={null}
  Nothing. Every packet eno2 receives continues up the kernel network stack
  exactly as before.
  ```

  ```text --rx-mode udp-port theme={null}
  IPv4 UDP packets whose DESTINATION port is 9000. Those stop reaching the
  kernel on eno2.
  ```

  ```text --rx-mode cidr theme={null}
  Every packet with a SOURCE address inside 10.0.0.0/8, whatever the protocol
  or port. Those stop reaching the kernel on eno2.
  ```

  ```text --rx-mode keep-management theme={null}
  Everything except management. Every packet eno2 receives is taken by Wireblast,
  but SSH and DNS to and from this host, plus ARP and IPv6 neighbour discovery,
  still reach the kernel, so the box stays reachable and your session survives.
  ```

  ```text --rx-mode all theme={null}
  EVERYTHING. Every single packet eno2 receives is taken by Wireblast and never
  reaches the kernel: SSH, DNS, ARP, the lot.
  ```
</CodeGroup>

## Honest limitations

These matter, because a filter that's broader than you assumed is how you lose a box:

* **`generated-flow` matches the IP pair only, not ports.** So any protocol between those two addresses gets redirected, not just this test's traffic. The underlying matcher can AND a source and destination CIDR, but can't also require a port.
* **`udp-port` and `tcp-port` match the destination port only.** Replies to a port Wireblast chose as its *source* aren't matched.
* **`cidr` matches the source address only.** Traffic you send toward that range is unaffected; traffic coming back from it is redirected in full.
* **`udp-port` and `tcp-port` are IPv4 only.** The address-based modes (`cidr`, `generated-flow`, `keep-management`, `all`) work for IPv6 as well.

Wireblast prints these under the plan rather than leaving you to discover them.

## Warnings you'll get

Point a filter at something load-bearing and it says so:

```text theme={null}
UDP port 53 is DNS: redirecting it takes DNS traffic away from the kernel
on this interface.
```

It knows about SSH (22), DNS (53), DHCP (67/68), NTP (123), BGP (179) and HTTPS (443).

With `--rx-mode cidr`, if your own client might be inside the range:

```text theme={null}
If your SSH client or DNS resolver is inside 10.0.0.0/8 and reachable over
eno2, you will lose it.
```

## Capturing everything safely: keep-management

Often you want to capture broadly on the very interface you're logged in over, without the ceremony of `all` and without losing your session. That's `--rx-mode keep-management`.

It redirects everything, then carves out the handful of things that keep the box reachable:

* **ARP and IPv6 neighbour discovery.** Without these the kernel loses the gateway's MAC within about a minute and the box goes unreachable, no matter what else you spared. These matter most.
* **SSH** to and from this host (TCP port 22).
* **DNS replies** (UDP and TCP source port 53).

So it's the denylist counterpart to the allowlist modes above: instead of "take only UDP 9000," it's "take everything except what would strand me." No `--allow-match-all`, no typed confirmation, because it can't cut you off.

```bash theme={null}
sudo wireblast -i eth1 --mode receive --rx-mode keep-management -d 60s
```

Two things to keep in mind:

* **Other services on the interface still lose their traffic.** A web server or database listening on this NIC stops receiving for the duration of the run. Your SSH and DNS keep working, but everything else is captured. That's the point, but it's worth knowing on a box that does more than testing.
* **The exceptions are scoped to the standard ports.** SSH on a non-standard port is not spared, and traffic *from* ports 22 or 53 toward the host isn't captured. For a measurement that's irrelevant; if you're hunting an adversary who picks those source ports, it matters.

If you administer the box over a **different** interface than the one you're capturing on, you don't need this at all: a plain filter on the capture interface can't touch your management NIC.

## The match-all guard

`--rx-mode all` is the one that can genuinely take a machine away from you. It has three independent layers of protection, and `--yes` gets past none of them.

<Steps>
  <Step title="Validation refuses it outright">
    Without `--allow-match-all`, the run never starts:

    ```text theme={null}
    --rx-mode all redirects EVERY packet on eno2 away from the kernel, taking SSH, DNS
    and all other traffic on this interface with it. Pass --allow-match-all if
    that is really what you want
    ```
  </Step>

  <Step title="The filter builder checks again">
    A second, independent check, so a code path that skipped validation still can't produce a match-all filter by accident.
  </Step>

  <Step title="You type the word">
    The run is marked dangerous, which means a confirmation you have to actually type:

    ```text theme={null}
    This run needs an explicit confirmation. Type 'yes' to continue.
    >
    ```

    One keystroke won't do it. Neither will `--yes`.
  </Step>
</Steps>

<Warning>
  **`--yes` does not bypass this, by design.** It answers ordinary confirmations, like "your SSH session runs over this interface" or "unlimited rate on the default-route interface". It's explicitly not a way to say yes to taking every packet from the kernel.
</Warning>

### Scripting it anyway

You can automate `--rx-mode all`. You just have to be explicit about it:

```bash theme={null}
sudo wireblast --no-tui -i eth1 --mode receive \
  --rx-mode all --allow-match-all --yes -d 60s
```

`--allow-match-all` is the non-interactive stand-in for typing `yes`. That's also why picking `all` in the wizard sets it for you: the review screen with its typed confirmation is already doing that job, so the flag isn't an extra gate there.

<Tip>
  Do this on an interface you are **not** logged in over. On a two-NIC box, manage over one and test on the other. That single habit makes every receive mode safe to experiment with.
</Tip>

## Receive-only runs

`--mode receive` transmits nothing at all, which is useful for turning a box into a sink that just counts what arrives:

```bash theme={null}
sudo wireblast --no-tui -i eno2 --mode receive \
  --rx-mode udp-port --rx-port 9000 -d 60s -y
```

The TX column becomes an idle block, no next-hop MAC is resolved, and the MTU check is skipped since nothing is being sent. It pairs with a sender in the [two-box guide](/guides/two-box).

Receive mode with `--rx-mode none` would do nothing whatsoever, so Wireblast catches that combination and says so.

## What isn't remembered

Wireblast [remembers your settings](/reference/keys-and-files) between runs, but never your consent. `--allow-match-all` and `--yes` are always dropped, and a saved `--rx-mode all` is downgraded to `none`.

Remembering that a previous run said yes to something dangerous would quietly carry that decision forward, which is exactly what these confirmations exist to prevent. Narrower receive modes are useful to remember, and are kept.
