Falco’s network connection rules are surprisingly good at catching things you’d never expect.

Let’s see what Falco can do. Imagine we have a simple web server running in a container. We want to know if anything else on the same host tries to connect to it, or if our web server tries to connect to something it shouldn’t.

Here’s a basic Falco rule that flags any outbound network connection from a container unless it’s to the expected external IP address of a database.

- rule: Unexpected outbound connection from webserver
  desc: "Detects outbound network connections from the webserver container to any IP other than the database."
  condition: container.name = "my-webserver" and net.connection.inbound = false and net.destination.ip != "192.168.1.100"
  output: "Unexpected outbound connection from webserver container (container=%container.name, to_ip=%net.destination.ip, to_port=%net.destination.port)"
  priority: WARNING

Now, let’s simulate a scenario. We have a container named my-webserver running. Normally, it only talks to 192.168.1.100 (our database).

# From inside the webserver container
curl http://example.com

If Falco is running with the rule above, and example.com resolves to an IP other than 192.168.1.100, you’ll get an alert like this:

15:30:01.123456789: Warning Unexpected outbound connection from webserver container (container=my-webserver, to_ip=93.184.216.34, to_port=80)

This works because Falco hooks into the Linux kernel (via libs/, audit, or eBPF) and sees every network syscall. The net.connection.inbound = false part tells Falco we’re interested in connections initiated from the container, and net.destination.ip != "192.168.1.100" is our explicit exclusion.

The real power comes from understanding the network events Falco exposes. You can track net.connection.protocol, net.destination.port, net.source.ip, net.source.port, and even container.name or proc.name to build highly specific rules.

Consider this rule: "Alert if the sshd process in a container tries to make any outbound network connection." This is highly suspicious, as sshd should typically only be listening for inbound connections.

- rule: sshd making outbound connections
  desc: "Detects when the sshd process within any container initiates an outbound network connection."
  condition: proc.name = "sshd" and net.connection.inbound = false
  output: "sshd process making unexpected outbound connection (container=%container.name, proc=%proc.name, to_ip=%net.destination.ip, to_port=%net.destination.port)"
  priority: CRITICAL

If an attacker compromises an SSH server in a container and tries to exfiltrate data or connect to a command-and-control server, this rule will fire. The proc.name = "sshd" focuses the alert on the specific process, and net.connection.inbound = false ensures we only flag outbound activity.

You can also flip this around. What if a process that shouldn’t be listening on the network starts doing so?

- rule: Unexpected process listening on network
  desc: "Detects processes other than known web servers or databases listening on common ports."
  condition: net.port > 0 and net.connection.inbound = true and proc.name != "nginx" and proc.name != "postgres" and proc.name != "mysqld"
  output: "Unexpected process listening on network (container=%container.name, proc=%proc.name, port=%net.port, proto=%net.protocol)"
  priority: HIGH

This rule flags any process that opens a listening socket (inbound connection) on any port, unless it’s a process we expect to do so (like nginx, postgres, or mysqld). The net.port > 0 and net.connection.inbound = true combination identifies processes that are acting as servers.

The net.protocol field is also useful. You can specify TCP or UDP. For instance, detecting unexpected UDP traffic from a web server might indicate a DNS tunneling attempt.

- rule: Webserver unexpected UDP traffic
  desc: "Detects if the webserver container initiates any UDP network connections."
  condition: container.name = "my-webserver" and net.connection.inbound = false and net.protocol = "udp"
  output: "Webserver initiating UDP connection (container=%container.name, to_ip=%net.destination.ip, to_port=%net.destination.port, proto=%net.protocol)"
  priority: MEDIUM

When you’re building these rules, remember that container.name and container.id are powerful for isolating events to specific applications. Similarly, proc.name and proc.cmdline let you get granular about the process initiating the connection.

One particularly effective strategy is to define a baseline of expected network behavior for your critical applications and then create explicit "DENY" rules for anything outside that baseline. For example, if your application server should only connect to your database and a specific external API, you’d have rules flagging any connection to any other IP address or port.

The real magic of Falco’s network rules is their ability to provide visibility into the implicit network policy of your system. You define what should happen, and Falco alerts you when something different happens, which is often the first indicator of a compromise or misconfiguration.

The next logical step after monitoring outbound connections is to monitor inbound connections to your critical services, ensuring only authorized sources can reach them.

Want structured learning?

Take the full Falco course →