Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Quick start

This walkthrough blocks one application’s outbound traffic, checks that the block applies only to that application, and then removes the profile. It assumes netscope is installed and netscoped is running; see Install.

All examples use sudo netscope --uid "$(id -u)". The $(id -u) is expanded by your shell before sudo, so it is your user ID, not root’s. If your user is in the netscope group and you have logged in again, you can omit both sudo and --uid.

1. Check the daemon

sudo systemctl status netscoped
netscope status

netscope status prints the daemon version, kernel, cgroup root, and profile table. If it exits 3, the daemon is not reachable:

netscope: daemon not running; start with: sudo systemctl start netscoped

Start it with sudo systemctl start netscoped, then retry.

2. Block one application

sudo netscope --uid "$(id -u)" add blocked --exe /usr/bin/curl --filter drop

This creates a profile named blocked for /usr/bin/curl with a filter whose default action is drop. The executable path is resolved from your current directory, so relative paths work, but an absolute path is clearer.

Test it:

curl --max-time 3 https://example.com

The request fails because every non-loopback destination from curl is dropped. Loopback is still accepted in drop mode; to see it working, run a local server in another terminal and fetch it:

python3 -m http.server 8080
curl --max-time 3 http://127.0.0.1:8080/

3. Inspect the profile

netscope list
sudo netscope status

list shows NAME, MODE, ENABLED, TARGET, ATTACHED, and PIDS for every profile, including disabled ones. status adds the daemon and cgroup header. A process that was started before the profile was added appears as late; a native app caught by the exec hook appears as pre-exec, and a Wine/Proton process caught opening the selected PE appears as pre-open.

Short-lived commands are usually gone before you look, so PIDS may be empty even though the block applied.

4. Add a narrow exception

Replace the profile with one that allows a single address:

sudo netscope --uid "$(id -u)" remove blocked
sudo netscope --uid "$(id -u)" add blocked --exe /usr/bin/curl --filter drop --allow-cidr 1.1.1.1/32
curl --max-time 5 https://1.1.1.1/

With this profile, https://1.1.1.1/ is allowed and every other destination is still dropped. Exceptions are destination CIDRs, not host names or ports. If the TLS certificate check fails on your system, use curl -k for this connectivity test only.

5. Select an app at launch

The point of the pre-exec path is that nothing wraps the application. For example:

sudo netscope --uid "$(id -u)" add browser --exe /usr/bin/firefox --filter allow --deny-cidr 192.168.0.0/16
firefox

Start firefox normally, from the desktop or a shell. The daemon catches the exec, places the process in the netscope/browser cgroup before its first socket, and nftables matches the cgroup. In this example the browser keeps internet access but cannot reach the 192.168.0.0/16 LAN. If the app is already running when you add the profile, it is attached on the next poll and its existing sockets are marked.

6. Route instead of filter

Route mode requires a tunnel interface that already exists, such as tun0 from WireGuard or OpenVPN:

sudo netscope --uid "$(id -u)" add routed --exe /usr/bin/curl --route tun0
curl --max-time 5 https://example.com

Traffic from curl is marked and looked up in netscope’s dedicated routing table. LAN destinations bypass the tunnel by default. To send LAN traffic through the tunnel too, add --include-lan:

sudo netscope --uid "$(id -u)" remove routed
sudo netscope --uid "$(id -u)" add routed --exe /usr/bin/curl --route tun0 --include-lan

See Route mode for the blackhole fallback and IPv6 behavior.

7. Route a Windows game through Wine or Proton

Point --wine at the .exe itself, not at a wine binary or a launcher:

sudo netscope --uid "$(id -u)" add game --wine /games/Game/Game.exe --route tun0

The path must be absolute, and the file must start with MZ — the DOS/PE header. Launch the game the way you normally do. When Wine opens the PE, the daemon holds the open, finds the Wine process whose command line names the PE, moves it into netscope/game, and then allows it. netscope status shows pre-open for that profile.

For a Steam Proton game, select the .exe the loader actually opens, usually under steamapps/common/<Game>/. A copy inside the Proton prefix (steamapps/compatdata/<appid>/pfx/drive_c/...) is a different file; select that path if the game is launched from it. --steam <appid> remains available when you prefer to match the Steam app instead.

8. Attach a running app by name

If the app is already running, or you do not want to store its install path, use --process:

sudo netscope --uid "$(id -u)" add game --process Overwatch.exe --route tun0

No path and no wrapper are involved. The daemon matches the process comm or its executable basename, and any argv basename of a Wine loader, case-insensitively. A new Wine/Proton launch is caught by the loader hold before its first socket; a process that was already running attaches on the next poll and is reported as late, with its existing sockets marked so their next packets follow the profile without a restart.

9. Share one process between two tools

When two programs need the same app, name it once per consumer with open; a second add for the same target is refused:

sudo netscope --uid "$(id -u)" open --consumer exitlink --name overwatch --process Overwatch.exe --route tun0
sudo netscope --uid "$(id -u)" open --consumer dropship --process Overwatch.exe --filter allow \
  --deny-cidr 64.224.26.0/23

Both consumers get the same profile and cgroup. Each owns its own policy; the last netscope close <profile> --consumer <id> removes the scope. See Shared scopes.

10. Run diagnostics

sudo netscope doctor

doctor exits 0 when every check passes and 1 when any fails. Run it as root (sudo netscope doctor); without root the root check fails and doctor exits 1. Add --json for machine-readable output. If it fails, see Troubleshooting.

11. Clean up

sudo netscope remove blocked
sudo netscope remove browser
sudo netscope remove routed
sudo netscope remove game

remove deletes the profile’s nftables table, routing rules, routes, and cgroup. Removing a profile does not stop the application; traffic returns to normal routing immediately.