Learn AppArmor - Network & Capabilities Rules
Episode 6 of 23

Learn AppArmor - Network & Capabilities Rules

Restricting processes through two dimensions beyond the filesystem: network rules for controlling TCP, UDP, Unix, and netlink sockets, capability rules for special kernel privileges, and the least privilege principle that unites them.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 5, you built profiles with aa-genprof and aa-logprof — and most of the rules that appeared were file rules: r, w, and x rights over specific paths. But there's an important boundary we haven't touched: file rules only govern access to objects on the filesystem.

A process locked down tightly on the filesystem still has two ways out: opening connections to the network, and calling capabilities in the kernel. A compromised web application could steal data and ship it to an attacker's server — all without ever touching an unauthorized file. Episode 6 closes both of those gaps at once.

Networking: The Often-Forgotten Exit Door

File rules are like locking the cabinets inside a building. As long as there's an open exit door, a thief doesn't need to break the cabinets — they can simply carry goods out through the door. In the real world, that "exit door" is the network socket.

AppArmor is deny by default for networking: if a profile mentions no network rule at all, the processes it governs cannot open any socket. This differs from plain Linux without AppArmor, which grants every process full network access.

The General Shape of Network Rules

Network rules have a layered syntax:

LinuxGeneral form of a network rule
network [domain] [type | protocol],

The most commonly used combinations:

LinuxCommon network rules
network inet tcp,
network inet udp,
network inet6 tcp,
network unix stream,
network netlink raw,

Let's break these down line by line:

  1. network inet tcp — allows IPv4 TCP. Almost every server serving HTTP, SSH, or a database needs this rule.
  2. network inet udp — allows IPv4 UDP. Useful for DNS resolvers and streaming services.
  3. network inet6 tcp — IPv6 TCP. You need this if your service listens on IPv6 addresses.
  4. network unix stream — allows Unix domain sockets of stream type. This isn't TCP networking — it's inter-process communication within a single host, including connections to local database sockets and DBus.
  5. network netlink raw — allows netlink sockets. Some utilities like ip or networking daemons need it to communicate with the kernel.

Note

The more specific a rule, the smaller the grant. network inet tcp is narrower than network inet, and network inet is narrower than bare network (every domain, every type). Always start from the most specific and add as denials appear — the same pattern as file rules in episode 5.

Restricting Down to Destination Addresses

TCP and UDP can even be restricted down to the destination address via the peer clause:

LinuxRestrict connections to a single host
network inet tcp peer=(addr=192.168.1.10),

This rule allows outbound TCP connections only to 192.168.1.10 — useful for an application that should only talk to an internal database, not the whole internet.

Deny Rules: Locking Down Parts

Because AppArmor denies by default, deny rules are usually used to revoke a broader grant — for example access granted by an abstraction (we cover this in episode 8). Deny always wins over allow:

LinuxA deny rule trimming a broader grant
deny network inet tcp peer=(addr=10.0.0.99),

If an abstraction grants network inet tcp without restriction, the line above ensures one particular address stays blocked.

Capability Rules: Special Kernel Keys

Capabilities are kernel privileges normally held only by root: mounting filesystems, changing a process's UID, opening raw sockets, and so on. In AppArmor, these grants are controlled per capability:

LinuxCommon capability rules
capability setuid,
capability setgid,
capability net_raw,
capability sys_admin,

Two of them deserve special attention:

  • capability net_raw — allows raw sockets. Needed for commands like ping that build ICMP packets by hand. Seems trivial, but raw sockets are the raw material for attacks like packet forging.
  • capability sys_admin — one of the most dangerous capabilities. It covers mount, most namespace operations, and many other things nearly equivalent to full control over the system. There's no common reason to give sys_admin to a web application.

Warning

Treat capability sys_admin like a building's master key. AppArmor won't refuse to write it — it will dutifully allow it. But once this capability is in a profile, all other restrictions become mere formalities. If an application "needs" sys_admin, question its architecture first, don't just add it to the profile.

A Third Dimension: rlimit

When it comes to capabilities, there's one complementary mechanism that often appears in production profiles: rlimit. AppArmor can bound a process's resources — number of open files, memory, CPU, and so on:

LinuxBound process resources
set rlimit nofile <= 1024,
set rlimit nproc <= 512,

The difference from capabilities: a capability answers "may you?", while an rlimit answers "how much?". Combining them lets a profile close the door while also limiting what can be done behind it — like handing out the key to a room and then limiting how much stuff may be brought in.

A Complete Profile Example

Let's combine everything. Imagine the daemon /usr/local/bin/myapp serving TCP connections on port 8080, writing logs, and pinging a monitoring host:

Linuxmyapp — network, capability, and rlimit rules
#include <tunables/global>
 
/usr/local/bin/myapp flags=(enforce) {
  #include <abstractions/base>
 
  network inet tcp,
  network inet6 tcp,
  network unix stream,
 
  capability setgid,
  capability setuid,
  capability net_raw,
 
  set rlimit nofile <= 1024,
  set rlimit nproc <= 64,
 
  /usr/local/bin/myapp mr,
  /etc/myapp/** r,
  /var/log/myapp/*.log w,
}

Notice what's not there: no network inet udp, no capability sys_admin. The application can't do its own DNS (it needs a resolver — we'll cover that in episode 8 via the nameservice abstraction), can't do raw sockets beyond what ping needs, and can't send data anywhere except over TCP. That's least privilege in practice.

Least Privilege: The Principle That Unites Everything

Network rules, capability rules, and rlimits all follow one principle: give a process only the rights it needs to perform its function — nothing more. Every rule you add expands the attack surface. A compromised process will never use rights you didn't grant.

The right flow:

  1. Start from a profile with no network or capability rules.
  2. Run the process, watch the denials in the logs.
  3. Add the narrowest possible rules for denials that are genuinely needed.
  4. Repeat until the process runs normally, then stop.

This is why AppArmor feels "restrictive" at first: deny by default does make many things fail on the first try. Episode 7 will give you the weapon to deal with it — reading denial logs correctly.

Conclusion

In episode 6 you've understood two permission dimensions beyond the filesystem: network rules that control sockets with deny-by-default and the peer clause for restricting addresses; capability rules that control special kernel privileges, including net_raw and sys_admin; and rlimits that bound resource counts. All of them follow the same least privilege principle.

Keys to take home:

  • Without a network rule, a process can't open any socket.
  • Restrict specifically: protocol first, then peer=(addr=...) if needed.
  • capability sys_admin is the master key — avoid it unless there's truly no alternative.

An overly tight profile will stop a process with denials — and you'll need the ability to read those denials to fix the profile without surrendering to the urge to "just delete all the rules". In episode 7, we dive into Debugging Denials & Logs: where AppArmor writes its traces, the apparmor="DENIED" format, the full observe-adjust-reload-verify flow, and aa-notify for automated notifications.