From e5ccdbfb75627ff521d43e47088ecd1ac893982f Mon Sep 17 00:00:00 2001 From: Christine Elisabeth Koppel Date: Wed, 3 Dec 2025 22:31:03 +0100 Subject: [PATCH] Initialize project structure with basic configuration files and main function --- .gitignore | 1 + .idea/.gitignore | 8 + .idea/discord.xml | 14 + Cargo.lock | 7 + Cargo.toml | 6 + nix-system-configs/new-server-notes.md | 1 + nix-system-configs/nixos-gateway.nix | 388 +++++++++++++++++++++++++ nix-system-configs/nixos-template.nix | 105 +++++++ nix-system-configs/old-server-notes.md | 123 ++++++++ src/main.rs | 3 + 10 files changed, 656 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/discord.xml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 nix-system-configs/new-server-notes.md create mode 100644 nix-system-configs/nixos-gateway.nix create mode 100644 nix-system-configs/nixos-template.nix create mode 100644 nix-system-configs/old-server-notes.md create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..104c42f --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7c9db51 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "the-prg-server-structure" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..652b5e8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "the-prg-server-structure" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/nix-system-configs/new-server-notes.md b/nix-system-configs/new-server-notes.md new file mode 100644 index 0000000..4e768b5 --- /dev/null +++ b/nix-system-configs/new-server-notes.md @@ -0,0 +1 @@ +# \ No newline at end of file diff --git a/nix-system-configs/nixos-gateway.nix b/nix-system-configs/nixos-gateway.nix new file mode 100644 index 0000000..80270d9 --- /dev/null +++ b/nix-system-configs/nixos-gateway.nix @@ -0,0 +1,388 @@ +{ + config, + pkgs, + lib, + ... +}: { + imports = [./hardware-configuration.nix]; + + ### Lix Package Manager ### + nixpkgs.overlays = [ + (final: prev: { + inherit + (prev.lixPackageSets.stable) + nixpkgs-review + nix-eval-jobs + nix-fast-build + colmena + ; + }) + ]; + + nix.package = pkgs.lixPackageSets.stable.lix; + + ### Network Configuration ### + networking.hostName = "prg-lan-gateway"; + networking.domain = "prg.dtu.dk"; + networking.useDHCP = false; + networking.useNetworkd = true; + + # Set MAC addresses to match DTU documentation + systemd.network.links."10-wan" = { + matchConfig. OriginalName = "eth*"; + matchConfig.Type = "ether"; + linkConfig = { + Name = "ens18"; + MACAddress = "2a:99:d6:03:dd:92"; # Hardcoded MAC, ensuring that DTU's sysadmin sees it is still the same + WakeOnLan = "off"; + }; + }; + + # Discuss removing/changing them? + systemd.network.links."20-lan1" = { + matchConfig.OriginalName = "eth*"; + matchConfig.Type = "ether"; + linkConfig = { + Name = "ens19"; + MACAddress = "0e:27:6a:11:a0:77"; + }; + }; + + systemd.network.links."30-lan2" = { + matchConfig.OriginalName = "eth*"; + matchConfig.Type = "ether"; + linkConfig = { + Name = "ens20"; + MACAddress = "42:d7:85:15:e1:ff"; + }; + }; + + # WAN Interface (ens18) + systemd.network.networks."10-wan" = { + matchConfig.Name = "ens18"; + address = ["130.225.91.242/27"]; + gateway = ["130.225.91.225"]; + networkConfig = { + IPv6AcceptRA = false; + DHCP = "no"; + }; + linkConfig = { + RequiredForOnline = "routable"; + MTUBytes = "1500"; + }; + }; + + # LAN Interface 1 (ens19) - Dual IP + systemd.network.networks."20-lan1" = { + matchConfig.Name = "ens19"; + address = [ + "10.123.123.1/24" + "192.168.0.1/24" + ]; + networkConfig = { + IPv6AcceptRA = false; + DHCP = "no"; + ConfigureWithoutCarrier = true; + }; + }; + + # LAN Interface 2 (ens20) + systemd.network.networks."30-lan2" = { + matchConfig.Name = "ens20"; + address = ["10.255.255.1/24"]; + networkConfig = { + IPv6AcceptRA = false; + DHCP = "no"; + ConfigureWithoutCarrier = true; + }; + }; + + # DNS Configuration + services.resolved = { + enable = true; + dnssec = "false"; + domains = ["prg.dtu.dk"]; + fallbackDns = ["1.1.1.1" "8.8.8.8" "130.225.89.2"]; + extraConfig = '' + DNSStubListener=no + ''; + }; + + # Kernel parameters for gateway/security + boot.kernel.sysctl = { + # IP forwarding (gateway) + "net.ipv4.ip_forward" = 1; + + # Reverse Path Filtering + "net.ipv4.conf.all.rp_filter" = 1; + "net.ipv4.conf.default.rp_filter" = 1; + + # SYN flood + "net.ipv4.tcp_syncookies" = 1; + "net.ipv4.tcp_syn_retries" = 5; + + # ICMP redirects / sending redirects + "net.ipv4.conf.all.accept_redirects" = 0; + "net.ipv4.conf.default.accept_redirects" = 0; + "net.ipv4.conf.all.send_redirects" = 0; + "net.ipv4.conf.default.send_redirects" = 0; + "net.ipv4.conf.all.secure_redirects" = 0; + + # Source route / routing protections + "net.ipv4.conf.all.accept_source_route" = 0; + "net.ipv4.conf.default.accept_source_route" = 0; + + # Log suspicious packets + "net.ipv4.conf.all.log_martians" = 1; + "net.ipv4.conf.default.log_martians" = 1; + + # ICMP hygiene + "net.ipv4.icmp_echo_ignore_broadcasts" = 1; + "net.ipv4.icmp_ignore_bogus_error_responses" = 1; + + # Performance + "net.ipv4.tcp_window_scaling" = 1; + + # Disable IPv6 if desired + "net.ipv6.conf.all.disable_ipv6" = 1; + "net.ipv6.conf.default.disable_ipv6" = 1; + + # Additional hardening knobs + "kernel.kptr_restrict" = 1; # hide kernel pointers in /proc + "kernel.dmesg_restrict" = 1; # restrict dmesg + "kernel.yama.ptrace_scope" = 1; # restrict ptrace + "fs.protected_hardlinks" = 1; + "fs.protected_symlinks" = 1; + }; + + # NAT Configuration + networking.nat = { + enable = true; + externalInterface = "ens18"; + internalInterfaces = ["ens19" "ens20"]; + forwardPorts = []; # Empty - no port forwarding + }; + + # Firewall Configuration + networking.firewall = { + enable = true; + + # Trusted LAN interfaces (all ports open) + trustedInterfaces = ["ens19" "ens20"]; + + # Interface-specific rules (keep permitted ports on LAN) + interfaces = { + ens19.allowedTCPPorts = [22 53]; + ens19.allowedUDPPorts = [53 67 123]; + ens20.allowedTCPPorts = [22 53]; + ens20.allowedUDPPorts = [53 67 123]; + }; + + # Tightened iptables rules using conntrack, drop INVALID, rate-limit ICMP and logging. + extraCommands = '' + # Default policies + iptables -P INPUT DROP + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + + # Drop invalid packets early + iptables -A INPUT -m conntrack --ctstate INVALID -j DROP + + # Allow loopback + iptables -A INPUT -i lo -j ACCEPT + + # Established/related + iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + + # Rate-limit ICMP (allow limited pings) + iptables -A INPUT -p icmp -m conntrack --ctstate NEW -m limit --limit 1/second --limit-burst 5 -j ACCEPT + + # Block new connections from WAN interface + iptables -A INPUT -i ens18 -m conntrack --ctstate NEW -j DROP + + # Log dropped packets (rate-limited) + iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-dropped: " --log-level 7 + ''; + + extraStopCommands = '' + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + ''; + }; + + # Hosts file + networking.extraHosts = '' + 130.225.91.242 prg-lan-gateway.prg.dtu.dk prg-lan-gateway + ''; + + # Time synchronization + time.timeZone = "Europe/Copenhagen"; + services.chrony = { + enable = true; + servers = ["time.cloudflare.com"]; + extraConfig = '' + makestep 1.0 3 + rtcsync + ''; + }; + + # Locale settings + i18n.defaultLocale = "en_US.UTF-8"; + i18n.extraLocaleSettings = { + LC_ADDRESS = "da_DK.UTF-8"; + LC_IDENTIFICATION = "da_DK.UTF-8"; + LC_MEASUREMENT = "da_DK.UTF-8"; + LC_MONETARY = "da_DK.UTF-8"; + LC_NAME = "da_DK.UTF-8"; + LC_NUMERIC = "da_DK. UTF-8"; + LC_PAPER = "da_DK.UTF-8"; + LC_TELEPHONE = "da_DK.UTF-8"; + LC_TIME = "en_DK.UTF-8"; + }; + + # Console keymap + # Change it back to Danish? + console.keyMap = "us"; + + # User configuration - + users.users.admin = { + isNormalUser = true; + description = "Gateway Administrator"; + extraGroups = ["wheel" "networkmanager" "systemd-journal"]; + openssh.authorizedKeys.keys = [ + # Christine's Hardware Key - Copy and change to the desired hardware keys + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3pjIXlpg7H9h1RrmdxbIRnDIdQvf/EZKI9PG2/rY7D openpgp:0x8BCD4992" + ]; + }; + + + # Passwordless sudo for wheel group + security.sudo.wheelNeedsPassword = false; + + # Hardware U2F support - Passwordless sudo with hardware key + security.pam.u2f = { + enable = true; + settings = { + authfile = "/etc/u2f_keys"; + cue = true; + pinverification = 0; # No PIN verification + userpresence = 1; # Require user presence (touch) + }; + }; + + # SSH Agent authentication + security.pam.enableSSHAgentAuth = true; + + # System packages + environment.systemPackages = with pkgs; [ + # Network tools + wget + curl + dig + tcpdump + ethtool + iptables + nftables + iproute2 + bridge-utils + netcat-gnu + traceroute + mtr + + # Monitoring + btop + htop + iotop + bandwhich + + # Editors + micro + vim + helix + + # System info + fastfetch + lshw + pciutils + usbutils + ]; + + # OpenSSH + services.openssh = { + enable = true; + settings = { + PermitRootLogin = "no"; + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + X11Forwarding = false; + + # Additional hardening + MaxAuthTries = 3; + LoginGraceTime = "20s"; + }; + extraConfig = '' + AllowUsers admin + ''; + openFirewall = false; # Manually configured in firewall section + }; + + # Tailscale VPN - We need to discuss about this long term + services.tailscale = { + enable = true; + useRoutingFeatures = "server"; + }; + + # Automatic upgrades + system.autoUpgrade = { + enable = true; # Set to true for automatic updates + dates = "daily"; + allowReboot = false; + }; + + # Nix garbage collection + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; + }; + + # Nix settings + nix.settings = { + experimental-features = ["nix-command" "flakes"]; + auto-optimise-store = true; + trusted-users = ["root" "@wheel"]; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # Boot configuration TO BE CHANGED ACCORDING TO INSTALL VERSION + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + timeout = 3; + }; + + # Kernel optimization + boot.kernelParams = [ + "quiet" + "splash" + ]; + + # Enable zram swap + zramSwap = { + enable = true; + memoryPercent = 50; + }; + + # Protect /tmp as a tmpfs with nosuid/nodev/noexec + fileSystems."/tmp" = { + device = "tmpfs"; + fsType = "tmpfs"; + options = ["mode=1777" "nosuid" "nodev" "noexec"]; + }; + + # System state version + system.stateVersion = "XX.XX"; +} diff --git a/nix-system-configs/nixos-template.nix b/nix-system-configs/nixos-template.nix new file mode 100644 index 0000000..7669fa1 --- /dev/null +++ b/nix-system-configs/nixos-template.nix @@ -0,0 +1,105 @@ +# Headless server configuration with Lix +{ + config, + pkgs, + lib, + ... +}: { + imports = [ + ./hardware-configuration.nix + ]; + + ## Use Lix, instead of Nix NixOS default ## + nixpkgs.overlays = [ + (final: prev: { + inherit + (prev.lixPackageSets.stable) + nixpkgs-review + nix-eval-jobs + nix-fast-build + colmena + ; + }) + ]; + + nix.package = pkgs.lixPackageSets.stable.lix; + + ### TO BE CHANGED ACCORDING TO INSTALL ### + + # Networking + networking.hostName = "server"; + networking.networkmanager.enable = true; + + # Time zone + time.timeZone = "Europe/Copenhagen"; + + # Locale + i18n.defaultLocale = "en_GB.UTF-8"; + # Also install Danish and Norwegian locales + i18n.extraLocales = ["da_DK.UTF-8" "nb_NO.UTF-8"]; + + # User account with hardware key support + users.users.admin = { + isNormalUser = true; + extraGroups = ["wheel" "networkmanager"]; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3pjIXlpg7H9h1RrmdxbIRnDIdQvf/EZKI9PG2/rY7D openpgp:0x8BCD4992" + ]; + }; + + # Hardware Key Passwordless Sudo + security.pam.u2f.enable = true; + security.pam.u2f.settings = { + authfile = "/etc/u2f_keys"; + authpending_file = ""; + pinverification = 0; + userpresence = 1; + }; + + # SSH Passwordless Sudo + security.pam.enableSSHAgentAuth = true; + security.pam.sshAgentAuth = { + enable = true; + authorizedKeysFiles = ["/etc/ssh/authorized_keys.d/admin"]; + }; + + # Essential packages + environment.systemPackages = with pkgs; [ + wget + curl + git + btop + htop + micro + vim + helix + fastfetch + ]; + + # OpenSSH + services.openssh = { + enable = true; + settings = { + PermitRootLogin = "no"; + PasswordAuthentication = false; + }; + }; + + # Tailscale - Think about how we manage this long term + services.tailscale.enable = true; + + # Garbage collection + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; + }; + + # Firewall + networking.firewall.allowedTCPPorts = [22]; + + nixpkgs.config.allowUnfree = true; + + ### TO BE CHANGED ACCORDING TO INSTALL VERSION ### + system.stateVersion = "XX.XX"; +} diff --git a/nix-system-configs/old-server-notes.md b/nix-system-configs/old-server-notes.md new file mode 100644 index 0000000..ac9f995 --- /dev/null +++ b/nix-system-configs/old-server-notes.md @@ -0,0 +1,123 @@ + + +# Old Server Notes + +--- + +# Gateway WAN Configuration - Essential Info + +## Network Details +``` +WAN IP: 130.225.91.242/27 +Netmask: 255.255.255.224 +Gateway: 130.225.91.225 +Gateway MAC: f0:7f:06:98:4a:64 +Network: 130.225.91.224/27 +Broadcast: 130.225.91.255 +Interface: ens18 +MTU: 1500 +Domain: prg.dtu.dk +Hostname: prg-lan-gateway +FQDN: prg-lan-gateway.prg.dtu.dk +``` + +## Upstream Path +``` +Gateway (130.225.91.225) → Cisco e11_0-1.bg106.internet.i3.cisco.net.local +Next Hop (192.38.93.34) → DTU edge router et2_12.90.sb-1g303-1 +``` + +## Interface Configuration +``` +Interface: ens18 +Type: Static IPv4 +Address: 130.225.91.242/27 +Gateway: 130.225.91.225 +No VLANs, No PPPoE, No MAC cloning +``` + +## Proxmox VM Configuration +``` +VM ID: 100 +Node: ve0 +Memory: 2GB +CPU: 2 cores (1 socket) +Disk: 10GB (local-lvm) +NIC Model: VirtIO + +Network Devices: + net0 (ens18): virtio=2A:99:D6:03:DD:92,bridge=vmbr1 ← WAN + net1 (ens19): virtio=0E:27:6A:11:A0:77,bridge=vmbr0 ← LAN + net2 (ens20): virtio=42:D7:85:15:E1:FF,bridge=vmbr2 ← LAN +``` + +## DNS Servers +``` +Primary: 1.1.1.1 (Cloudflare) +Secondary: 8.8.8.8 (Google) +Tertiary: 130.225.89.2 (DTU) +Domain: prg.dtu.dk +Search: prg.dtu.dk +``` + +## NTP Servers +``` +time.cloudflare.com +``` + +## Firewall Rules + +### NAT (Outbound) +``` +Chain: POSTROUTING +Action: Masquerade all traffic on interface ens18 +``` + +### Filter (Inbound) +``` +Accept: Loopback (lo) +Accept: Established/Related connections +Drop: All other traffic from ens18 (WAN) +Default: Accept (for other interfaces) +``` + +### Port Forwarding +``` +None configured +``` + +## System Requirements +``` +IP Forwarding: Enabled (net.ipv4.ip_forward=1) +Reverse Path Filtering: Enabled (net.ipv4.conf.all.rp_filter=1) +SYN Cookies: Enabled (net.ipv4.tcp_syncookies=1) +Accept ICMP Redirects: Disabled (net.ipv4.conf.all.accept_redirects=0) +Send ICMP Redirects: Disabled (net.ipv4.conf.all.send_redirects=0) +Accept Source Route: Disabled (net.ipv4.conf.all.accept_source_route=0) +Log Martian Packets: Enabled (net.ipv4.conf.all.log_martians=1) +Ignore Broadcast Pings: Enabled (net.ipv4.icmp_echo_ignore_broadcasts=1) +Ignore Bogus ICMP Errors: Enabled (net.ipv4.icmp_ignore_bogus_error_responses=1) +``` + +## Hosts File +``` +127.0.0.1 localhost +130.225.91.242 prg-lan-gateway.prg.dtu.dk prg-lan-gateway +::1 localhost ip6-localhost ip6-loopback +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +``` + +## LAN Interfaces +``` +ens19: 10.123.123.1/24, 192.168.0.1/24 (dual IP) +ens20: 10.255.255.1/24 +``` + +## Critical Notes +``` +Platform: Proxmox VM (node ve0, VM ID 100) +WAN MAC: 2A:99:D6:03:DD:92 (must preserve for rebuild maybe, due to DTU being very thorough maybe) +WAN Bridge: vmbr1 (not vmbr0) +IPv6: Not configured +``` \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..43560ff --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, this will be changed later!"); +}