Packages

Elixir library for working with Linux nftables rules. Provides high-level APIs for building tables, chains, rules, maps and sets. Works with NFTables.Port for communicating with the kernel firewall.

Current section

Files

Jump to
nftables examples 01_sysctl_management.exs
Raw

examples/01_sysctl_management.exs

#!/usr/bin/env elixir
# Sysctl Network Parameter Management Example
#
# This example demonstrates how to safely manage Linux kernel network
# parameters via NFTables's sysctl API.
#
# Features:
# - Read/write network kernel parameters
# - High-level helpers for common operations
# - Parameter whitelist security
# - Value validation
#
# Usage:
# mix run examples/01_sysctl_management.exs
#
# Requirements:
# - Root privileges or CAP_NET_ADMIN capability
# - Run: sudo setcap cap_net_admin=ep priv/port_nftables
#
# Note: This example will READ parameters but only WRITES if you
# explicitly confirm. Original values are restored.
Mix.install([{:nftables, path: "."}])
defmodule SysctlManagement do
@moduledoc """
Demonstrates sysctl network parameter management with NFTables.
"""
alias NFTables.{Sysctl, Sysctl.Network}
def run do
IO.puts("=== NFTables Sysctl Management Example ===\n")
# Start NFTables
{:ok, pid} = NFTables.start_link()
IO.puts("✓ NFTables started\n")
# 1. Read current network parameters
demo_read_parameters(pid)
# 2. High-level helpers (read-only demo)
demo_high_level_helpers(pid)
# 3. Composite operations (optional write demo)
demo_composite_operations(pid)
IO.puts("\n=== Example complete! ===")
end
defp demo_read_parameters(pid) do
IO.puts("=== 1. Reading Current Network Parameters ===\n")
params = [
{"net.ipv4.ip_forward", "IPv4 forwarding"},
{"net.ipv4.tcp_syncookies", "TCP SYN cookies (DDoS protection)"},
{"net.ipv4.conf.all.rp_filter", "Reverse path filtering (anti-spoofing)"},
{"net.ipv4.conf.all.accept_redirects", "Accept ICMP redirects"},
{"net.ipv4.icmp_echo_ignore_all", "Ignore ping requests"},
{"net.ipv6.conf.all.forwarding", "IPv6 forwarding"}
]
for {param, description} <- params do
case Sysctl.get(pid, param) do
{:ok, value} ->
IO.puts("✓ #{description}")
IO.puts(" Parameter: #{param}")
IO.puts(" Current value: #{value}\n")
{:error, reason} ->
IO.puts("✗ #{description}")
IO.puts(" Parameter: #{param}")
IO.puts(" Error: #{reason}\n")
end
end
# Try reading connection tracking max (might not be available on all systems)
case Sysctl.get(pid, "net.netfilter.nf_conntrack_max") do
{:ok, value} ->
IO.puts("✓ Connection tracking maximum")
IO.puts(" Parameter: net.netfilter.nf_conntrack_max")
IO.puts(" Current value: #{value}\n")
{:error, _} ->
IO.puts("ℹ Connection tracking not available on this system\n")
end
end
defp demo_high_level_helpers(pid) do
IO.puts("=== 2. High-Level Helper Functions ===\n")
# Check IPv4 forwarding status
case Network.ipv4_forwarding_enabled?(pid) do
{:ok, enabled} ->
status = if enabled, do: "ENABLED", else: "DISABLED"
IO.puts("IPv4 Forwarding: #{status}")
{:error, _} ->
IO.puts("IPv4 Forwarding: Unable to check")
end
# Get connection tracking max
case Network.get_conntrack_max(pid) do
{:ok, max} ->
IO.puts("Connection Tracking Max: #{max}")
{:error, _} ->
IO.puts("Connection Tracking Max: Not available")
end
IO.puts("")
end
defp demo_composite_operations(pid) do
IO.puts("=== 3. Composite Operations (Router & Security Hardening) ===\n")
IO.puts("This section demonstrates:")
IO.puts(" • Network.configure_router/2 - Configure router settings")
IO.puts(" • Network.harden_security/1 - Apply security hardening\n")
IO.puts("⚠️ WARNING: These operations will MODIFY system parameters!")
IO.puts("Do you want to run the write demo? (original values will be restored)")
IO.write("Continue? [y/N]: ")
case IO.gets("") |> String.trim() |> String.downcase() do
"y" ->
run_write_demo(pid)
_ ->
IO.puts("\nSkipped write demo.")
IO.puts("\nTo manually test composite operations:")
IO.puts("""
# Configure as router
:ok = Network.configure_router(pid,
ipv4_forwarding: true,
ipv6_forwarding: true,
syncookies: true,
send_redirects: false
)
# Harden security settings
:ok = Network.harden_security(pid)
# Individual operations
:ok = Network.enable_ipv4_forwarding(pid)
:ok = Network.enable_syncookies(pid)
:ok = Network.set_conntrack_max(pid, 131072)
:ok = Network.ignore_ping(pid) # Stealth mode
""")
end
end
defp run_write_demo(pid) do
IO.puts("\n=== Running Write Demo ===\n")
# Store original values
original_values = store_original_values(pid)
# Demo: Enable IPv4 forwarding
IO.puts("1. Enabling IPv4 forwarding...")
case Network.enable_ipv4_forwarding(pid) do
:ok ->
{:ok, value} = Sysctl.get(pid, "net.ipv4.ip_forward")
IO.puts(" ✓ IPv4 forwarding set to: #{value}")
{:error, reason} ->
IO.puts(" ✗ Failed: #{reason}")
end
# Demo: Enable SYN cookies
IO.puts("\n2. Enabling TCP SYN cookies (DDoS protection)...")
case Network.enable_syncookies(pid) do
:ok ->
{:ok, value} = Sysctl.get(pid, "net.ipv4.tcp_syncookies")
IO.puts(" ✓ TCP SYN cookies set to: #{value}")
{:error, reason} ->
IO.puts(" ✗ Failed: #{reason}")
end
# Demo: Harden security
IO.puts("\n3. Applying security hardening...")
case Network.harden_security(pid) do
:ok ->
IO.puts(" ✓ Security hardening applied:")
IO.puts(" - Reverse path filtering: enabled")
IO.puts(" - Source routing: disabled")
IO.puts(" - ICMP redirects: disabled")
IO.puts(" - SYN cookies: enabled")
{:error, reason} ->
IO.puts(" ✗ Failed: #{reason}")
end
# Restore original values
IO.puts("\n4. Restoring original values...")
restore_original_values(pid, original_values)
IO.puts(" ✓ Original values restored")
end
defp store_original_values(pid) do
params = [
"net.ipv4.ip_forward",
"net.ipv4.tcp_syncookies",
"net.ipv4.conf.all.rp_filter",
"net.ipv4.conf.default.rp_filter",
"net.ipv4.conf.all.accept_source_route",
"net.ipv4.conf.default.accept_source_route",
"net.ipv4.conf.all.send_redirects",
"net.ipv4.conf.default.send_redirects",
"net.ipv4.conf.all.accept_redirects",
"net.ipv4.conf.default.accept_redirects",
"net.ipv6.conf.all.accept_redirects",
"net.ipv6.conf.default.accept_redirects"
]
Enum.map(params, fn param ->
case Sysctl.get(pid, param) do
{:ok, value} -> {param, value}
{:error, _} -> {param, nil}
end
end)
|> Enum.filter(fn {_param, value} -> value != nil end)
end
defp restore_original_values(pid, original_values) do
for {param, value} <- original_values do
Sysctl.set(pid, param, value)
end
end
end
# Run the example
SysctlManagement.run()