Sometimes application-level controls are not enough. If a plugin or service keeps making outbound calls you cannot disable cleanly, you can block specific URL paths at the network layer with iptables.

This is a narrow operational control, not a general egress policy. Use it when you need to stop a known bad outbound pattern quickly and can accept the maintenance cost of host-level firewall rules.

Operational context

  • When to use this: a process makes repeated outbound calls to endpoints you want to block, and application configuration does not provide a reliable off switch.
  • What it reduces: unwanted outbound traffic to specific URL paths.
  • Tradeoff: string matching in iptables is brittle, host-specific, and harder to audit than application-level controls or a default-deny egress policy.

Requirements

Your kernel must be built with Netfilter string match support.

Critical limitation: HTTPS traffic

iptables string matching inspects packet payloads. That works for plain HTTP paths, but it does not reliably work for HTTPS because the request path is encrypted inside TLS.

For HTTPS traffic, consider:

  • fixing or disabling the application behavior directly
  • blocking by destination IP or CIDR if the endpoint is stable
  • routing outbound traffic through an HTTP proxy where requests can be controlled intentionally
  • using DNS policy controls for domain-level blocking
  • applying a default-deny egress policy with explicit allow lists

Do not treat the string match approach as a complete web egress firewall.

Example rules

iptables -A OUTPUT -p tcp -m string --string "/webnus.net/plugin-api/verify" --algo kmp -j REJECT --reject-with tcp-reset
iptables -A OUTPUT -p tcp -m string --string "/webnus.net/addons-api/verify" --algo kmp -j REJECT --reject-with tcp-reset

Rule breakdown:

  • -A OUTPUT appends a rule to the outbound chain.
  • -p tcp limits matching to TCP traffic.
  • -m string --string "PATTERN" --algo kmp matches the payload against the given pattern using the KMP algorithm.
  • -j REJECT --reject-with tcp-reset resets the connection instead of silently dropping it.

Scope rules to a process user

When possible, scope the block to the Unix user that runs the process. For example, WordPress behind PHP-FPM may run as www-data:

iptables -A OUTPUT \
  -p tcp \
  -m owner --uid-owner www-data \
  -m string --string "/webnus.net/plugin-api/verify" --algo kmp \
  -j REJECT --reject-with tcp-reset

This limits the blast radius. A host-wide OUTPUT rule can surprise unrelated services, package managers, health checks, or monitoring agents.

Persist rules across reboot

Temporary rules disappear after reboot. On Debian or Ubuntu, persist them with:

sudo apt install iptables-persistent
sudo netfilter-persistent save

Or export and restore them explicitly:

sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo iptables-restore < /etc/iptables/rules.v4

On newer systems, nftables may be the preferred firewall backend. If you are already using nftables, keep the policy there rather than mixing management models.

Broader approach

A more robust long-term model is default-deny egress with an explicit allow list for required destinations. That is more work to operate, but easier to reason about than pattern-specific blocking rules.

See this Ask Ubuntu thread for a starting point.

Verification

After applying the rules:

  1. Confirm the blocked endpoint is no longer reachable from the affected host.
  2. Confirm legitimate application traffic still works.
  3. Confirm the block still behaves after reboot if this is meant to be permanent.
  4. Check application logs for retries, timeout amplification, or unexpected fallback behavior.

Related note

I originally used this pattern while debugging slow WordPress admin performance caused by a plugin making excessive outbound verification calls. See How to fix slow WordPress admin.

Related work

This egress-control pattern supports RBAC and access governance and production security work in Selected operational work.