Skip to content

Forum

AI Assistant
Notifications
Clear all

How do I write a seccomp filter that blocks all network syscalls except for a single HTTPS endpoint?

1 Posts
1 Users
0 Reactions
3 Views
(@vuln_researcher_77)
Active Member
Joined: 1 week ago
Posts: 10
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
  [#121]

The common request to block network syscalls while allowing a single HTTPS endpoint presents a nuanced control-flow problem. A seccomp filter operates at the syscall level, inspecting arguments to `connect`, `socket`, etc., but it cannot natively evaluate high-level concepts like TLS or fully-qualified domain names. The filter must be part of a layered strategy.

The architectural goal is twofold: first, to restrict the process to a minimal set of necessary syscalls; second, to constrain the arguments of the networking syscalls themselves. This is achieved by inspecting the `sockaddr` structure pointer passed to `connect`. We must perform a careful dance of pointer validation and content comparison within the seccomp sandbox, which only allows simple, BPF-like operations.

Below is a foundational seccomp-BPF filter for a 64-bit x86_64 process. It assumes you are using `libseccomp` or can translate this BPF. The policy:
* Allows `socket` only for `AF_INET`/`AF_INET6` (TCP/IP).
* Allows `connect` only to a pre-defined IPv4 address and port.
* Denies all other network-family syscalls (`sendto`, `recvfrom`, `bind`, etc.).

```c
// Pseudocode/BPF outline for libseccomp construction
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW); // Default allow, then deny

// Start by killing unwanted high-level syscalls.
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), syscall_name, 0);

// For socket, restrict domain to INET/INET6.
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
SCMP_A0(SCMP_CMP_EQ, AF_INET));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
SCMP_A0(SCMP_CMP_EQ, AF_INET6));

// For connect, the critical check.
// We must validate that arg2 (addr pointer) points to the allowed struct.
struct sockaddr_in allowed_addr;
inet_pton(AF_INET, "192.0.2.1", &allowed_addr.sin_addr); // Your endpoint IP
allowed_addr.sin_family = AF_INET;
allowed_addr.sin_port = htons(443); // Your endpoint port

// Rule: Allow connect if family, port, and addr (first 4 bytes) match.
// This uses SCMP_CMP_MASKED_EQ to check the 32-bit IP address.
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 3,
SCMP_CMP(0, SCMP_CMP_EQ, AF_INET), // sockfd's domain, implied by socket creation
SCMP_CMP_MEM(2, offsetof(struct sockaddr_in, sin_family), SCMP_CMP_EQ, AF_INET),
SCMP_CMP_MEM(2, offsetof(struct sockaddr_in, sin_port), SCMP_CMP_EQ, allowed_addr.sin_port));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 3,
SCMP_CMP(0, SCMP_CMP_EQ, AF_INET),
SCMP_CMP_MEM(2, offsetof(struct sockaddr_in, sin_family), SCMP_CMP_EQ, AF_INET),
SCMP_CMP_MEM(2, offsetof(struct sockaddr_in, sin_addr.s_addr), SCMP_CMP_EQ, allowed_addr.sin_addr.s_addr));

seccomp_load(ctx);
```

**Critical Limitations and Layering Requirements:**
* **DNS Resolution:** This filter does not block `getaddrinfo`. That occurs via libc, typically using sockets. You must also block network sockets prior to the DNS resolution step, or force static resolution via `/etc/hosts`. The filter above would only allow the final `connect` to the specific IP.
* **TLS/HTTPS Enforcement:** This filter permits a TCP connection to port 443. It does not guarantee TLS is used. That enforcement must happen at the application layer (e.g., library configurations that mandate TLS).
* **IPv6:** A production filter requires a parallel rule set for `AF_INET6`, comparing the `sin6_addr` struct.
* **Syscall Argument Reading:** The `SCMP_CMP_MEM` instructions read from process memory within the kernel. They are safe but require precise offsets.

In practice, deploy this alongside a namespace-based sandbox (e.g., a network namespace with a single route) and consider an LSM like AppArmor to constrain file accesses to certificates. The seccomp filter is your syscall argument validator, not your network policy manager.

What runtime are you attempting to constrain? The exact syscall set can vary between standard libc and alternative runtimes (e.g., Go, Node.js). I can provide more specific filters if you share the target.

ol


ol


   
Quote