VA1DER Wiki

Official Wiki of the Dark Side

User Tools

Site Tools


wiki:debianmailserver

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
wiki:debianmailserver [2024/08/23 19:51] – [VeraCrypt] Tweaks va1derwiki:debianmailserver [2024/09/28 01:29] (current) va1der
Line 3: Line 3:
 **// **//
  
-Say Goodbye to Google, you're setting up the cadilac of e-mail systems.  With it you can host many domains worth of email, give yourself and your family and friends the best vanity addresses in the world, swoop in to save the day for clubs and organizations who don't have the expertise or cash, and do it all on a small budget.  You don't need all that much in the way of a server to accomplish it.+Say Goodbye to Google, you're setting up the Cadilac of e-mail systems.  With it you can host many domains worth of email, give yourself and your family and friends the best vanity addresses in the world, swoop in to save the day for clubs and organizations who don't have the expertise or cash, and do it all on a small budget.  You don't need all that much in the way of a server to accomplish it.
  
-There are easier virtual domain e-mail solutions, like [[https://mailinabox.email/|Mail-in-a-box]], but these can hide too much of the engine.  Their design decisions and nuts-and-bolts are often poorly documented, leaving it difficult to add pieces, and almost impossible to change components.+Doing it this way is setting up a lot of moving parts.  So first think about whether you perhaps want a more turn-key solution like [[https://mailinabox.email/|Mail-in-a-box]].
  
-However doing it this way is setting up a lot of moving parts.  Even following these instructions you can expect this to take a few days. +That said, at the end of this process you will have an email server you knowv inside and out, one you can add arbitrary domains to, one that is very secure from outside access and which is even somewhat secure from internal (VPS host) access.
- +
-That said, at the end of this process you will have an email server you can add arbitrary domains to, one that is very secure from outside access and which is even somewhat secure from internal (VPS host) access.+
  
 ---- ----
Line 15: Line 13:
 ====== Requirements ====== ====== Requirements ======
 You will need the following: You will need the following:
-  - **Static IP address with PTR (reverse DNS) capability.**\\ If you don't have a genuine static IP address from a provider that is willing to put in a reverse DNS PTR record, then don't attempt this.  Period.  Without it your email just won't be deliverable.  Most VPS providers that give you a static IP will set up a PTR, though mine required me to send them my photo ID. +  - **Static IP address with PTR (reverse DNS) capability.**++☛|**(**A reverse DNS PTR record is required for deliverability.  Outgoing emails from your server will end up in the spam folders or jsut be dropped outright forever by every major email player without a reverse DNS name that matches your forward DNS name.  If you don't have a genuine static IP address from a provider that is willing to put in a reverse DNS PTR record, then don't attempt this.  Period.  Most VPS providers that give you a static IP will set up a PTR, though mine required me to send them my photo ID.**)**++ 
-  - **A shiny new domain name and the ability to control the DNS for it.**\\  The instructions below assume you are going to self-host your own DNS, but that requires you to have two unique IP addresses and a domain provider who will make the glue records for you.  You don't have to self-host your DNS, but you will need a registrar that gives you good control of your DNS.  You need one real domain that you own.  Every other domain you host only needs to put an MX record on their DNS to say you are handling their email. +  - **A shiny new domain name and the ability to control the DNS for it.**++☛|**(**The instructions below assume you are going to self-host your own DNS, but that requires you to have two unique IP addresses and a domain provider who will make the glue records for you.  You don't have to self-host your DNS, but you will need a registrar that gives you good control of your DNS.  You need one real domain that you own.  Every other domain you host only needs to put an MX record on their DNS to say you are handling their email.  [[https://www.pairdomains.com/|Pair Domains]] is one registrar I can recommend as giving exceptional (and free) DNS control right with your domain.**)**++ 
-  - **Actual server "hardware".**\\ I personally use a VPS with 2 cores, 80GiB of space, and 4GiB of RAM.  Many of my design decisions are specifically tailored to reducing memory and CPU footprint.  The first VPS I ran back on Debian 7 had half a core (one core shared between two VPSsand 1GiB of RAM.  This is still a feasible setup. +  - **Server.**++☛|**(**A physical or Virtual Private Server.  Going with a VPS is the common solution.  Experience showed a VPS with ½ core (one core shared between two VPSs), 1GiB RAM and 10GiB storage is a feasible minimal server for a small one or two domain setup.  Something more robust would be 2 cores, 4GiB RAM, 40GiB storage.  Many of the design decisions here are specifically tailored to reducing memory and CPU footprint.**)**++ 
-  - **A workstation.**\\ This probably goes without saying, but you'll need a computer to work from to build this.  On it you'll need:+  - **A workstation with:**
     - WireGuard "client"     - WireGuard "client"
-    - SSH - a good modern one with scp capability and sntrup761x25519 support.  That means OpenSSH (9+), TinySSH (20210601+), or for Windows, PuTTY (0.78+) / WinSCP (6.2+) +    - SSH  Either OpenSSH (9+) or, for Windows, PuTTY (0.78+) / WinSCP (6.2+) 
-  - **Watchdog computer**\\ It isn't an //absolute// requirement, but for the internal security portion (where we encrypt the server's mail and database storage) we need a watchdog computer.  By that what is meant is an always-on always-on computer, one that is hopefully inside your local LAN and which you can trust implicitly.  It needs to be able to perform periodic checks (ie: cron).  A spare OpenWRT router/device is an eminently great, energy efficient, and cheap solution.+  - **Watchdog computer/device**++☛|\\**(**It isn't an //absolute// requirement, but for the internal security portion (where we encrypt the server's mail and database storage) we need a watchdog computer.  By that what is meant is an always-on always-on computer, one that is hopefully inside your local LAN and which you can trust implicitly.  It needs to be able to perform periodic checks (ie: cron).  A spare OpenWRT router/device is an eminently great, energy efficient, and cheap solution.**)**++
  
 ---- ----
Line 41: Line 39:
  
 ===== Considerations ===== ===== Considerations =====
 +Some of the design considerations which may need a little explanation:
  
-**Web Server:** The decision to go with Lighttpd has been revisted several times in the iterations leading up to this one.  Lighttpd is in the significant minority of installations today.  Nginex is slightly more performant on high-resource systems, but Lighttpd is still by far the best way to squeeze every megabyte out of your server. If you are running on a VPS and are paying for every megabyte, then Lighttpd is the way to go.  That said, it hasn't always been the easiest choice, and might mean a learning curve for you in the future when you add pieces.  Many instructions ust assume you're going to be using Apache or Nginex.+**Web Server:** This design uses Lighttpd.  Lighttpd is one of Debian's three officially supported web servers, but today is in the significant minority of installations.  The decision to continue with Lighttpd has been revisited several times in the iterations leading up to this one.  While it is true that Nginex is slightly more performant on high-resource systems, Lighttpd is still by far the best way to squeeze every megabyte out of your server. If you are running on a VPS and are paying for every megabyte, then Lighttpd is the way to go.
  
-**DKIM:**  OpenDKIM is the DKIM provider most people think of.  But it [[https://sourceforge.net/projects/opendkim/files/|hasn't been updated]] //since// Debian 7 in 2015.  A new player in town is dkimpy-milter, a switch made with the previous, Debian 11, iteration and it has performed excellently.  Even if it is written in Python. ;-)+**DKIM:**  OpenDKIM is the DKIM provider most people think of.  But it [[https://sourceforge.net/projects/opendkim/files/|hasn't been updated]] //since// Debian 7 in 2015.  A new player in town is dkimpy-milter, a switch made with the previous, Debian 11, iteration of this procedure, and it has performed excellently.  Even if it is written in Python. ;-)
  
-**Packaging:** A major design consideration has been to avoid the use of any third party package/dependency systems (Composer, PyPI, Go-anything, etc).  Some projects, like RoundCube, have officially adopted Composer as their plugin distribution mechanism.  This has no place on a production server, which is what we're making here.  All modules, libraries, and plugins are either supplied by Debian packages or are vetted and manually downloaded.  +**External Packaging:** A major design consideration has been to avoid the use of //any// third party packaging/dependency systems (Composer, PyPI, Go-anything, etc).  Some projects, like RoundCube, have officially adopted Composer as their plugin distribution mechanism.  This has no place on a production server, which is what we're making here.  All modules, libraries, and plugins are either supplied by Debian packages or are vetted and manually downloaded.
  
  
Line 55: Line 54:
  
 ====== Procedure ====== ====== Procedure ======
-We are starting here from the point where you have a brand new VPS you are starting up for the first time.  Even if you've already been using your server for some time, you may want to read these steps.+We are starting from the point where you have a brand new VPS you are starting up for the first time.  Even if you've already been using your server for some time, you may want to read these initial steps.
  
-NOTE: Command-lines below assume the use of ''%%joe%%'' as my a text editor.  It's a bit more old school than ''%%nano%%'', so feel free to adjust to your preferences.+NOTE: Command-lines below assume the use of ''%%joe%%'' as a text editor.  It's a bit more old school than ''%%nano%%'', so feel free to adjust to your preferences.
  
 ===== Phase 1 - Batten the Hatches (External Security) ===== ===== Phase 1 - Batten the Hatches (External Security) =====
-You've got a shiny new VPS or server.  Your first consideration is to secure it.  András Stribik said it best when he said "my goal with this .. is to make NSA analysts sad".  This is absolutely our goal.+You've got a shiny new VPS or server.  Your first consideration is to secure it.  The goal here, in the words of András Stribikis to make NSA analysts sad. 
 + 
 +Security goals: 
 +  - 256-bit level security throughout (ie: <m>2^256</m> operations to crack) 
 +  - All keymat transfers (including session keys) protected by crypto as strong as the security level of the keymat.  256-bit keymat should never be transported without being protected by crypto that matches its security level 
 +  - Post-Quantum safe 
 +  - Redundant security - SSH over WireGuard
  
-If your VPS provider is like mine, you'll get a remote console using something like VNC-over-https.  First order of business, make sure you've got nothing listening on it, and if there is, if it's something that hasn't yet been vetted, then shut it down:+If your VPS provider is like mine, you'll start with a remote console using something like VNC-over-https.  First order of business, make sure you've got nothing listening on your server, and if there is, and you haven't yet ensured it's secure, then shut it down.  Take a look at what's listening:
   $ sudo netstat -tuelnp   $ sudo netstat -tuelnp
  
Line 70: Line 75:
 Next we install WireGuard and secure SSH.  WireGuard gives you the ability to use pre-shared keys, which takes the guesswork out of whether or not any KEX is secure.  But since you don't have physical access to the server, you are going to be generating the pre-shared keymat on the server then transferring it off.  This means you need to establish a channel offering a level of security //equal or higher// than the keymat you are transferring.  It doesn't make much sense to generate a 256-bit security level pre-shared key on your server, and then transfer it off over ssh that is itself secured with only a 128-bit equivalent KEX. Next we install WireGuard and secure SSH.  WireGuard gives you the ability to use pre-shared keys, which takes the guesswork out of whether or not any KEX is secure.  But since you don't have physical access to the server, you are going to be generating the pre-shared keymat on the server then transferring it off.  This means you need to establish a channel offering a level of security //equal or higher// than the keymat you are transferring.  It doesn't make much sense to generate a 256-bit security level pre-shared key on your server, and then transfer it off over ssh that is itself secured with only a 128-bit equivalent KEX.
  
-Once this is done, it's recommended you always communicate with your sever by ssh OVER WireGuard.+Once this is done, it's recommended you always communicate with your sever by SSH OVER WireGuard.
  
 ==== SSH over WireGuard Remote Server Procedure ==== ==== SSH over WireGuard Remote Server Procedure ====
-This procedure assumes you don't have physical access to your server.  If you do, then you can sneaker-net transfer the keymat and you can likely figure out how to do that:+This procedure will let you use an untrusted and insecure connection to create a secure one in a way that is likely safe from even state-level actors unless they employ rubber-hose cryptography.  It assumes you don't have physical access to your server.  If you do, then you can sneaker-net transfer the keymat and you can likely figure out how to do that:
   - Create a temporary configuration in wireguard on your workstation.  This will generate a local private and public key.  All you need at this stage is the public key.  __Note it__.\\ For ++Windows| bring up WireGuard's window from the task tray, click the ↓ symbol beside "Add tunnel" and select "Add empty tunnel..."++\\ For ++Linux| ''%%$ wg genkey | tee TEMPORARY.key | wg pubkey > TEMPORARY.pub%%''++   - Create a temporary configuration in wireguard on your workstation.  This will generate a local private and public key.  All you need at this stage is the public key.  __Note it__.\\ For ++Windows| bring up WireGuard's window from the task tray, click the ↓ symbol beside "Add tunnel" and select "Add empty tunnel..."++\\ For ++Linux| ''%%$ wg genkey | tee TEMPORARY.key | wg pubkey > TEMPORARY.pub%%''++
   - Transfer (''%%wget%%'' on the server) the wireguard interface configuration (''%%/etc/network/interfaces.d/wg0%%'')), the ifup helper script (''%%/etc/wireguard/wg0.up%%''), and setup script (''%%wgnetgen%%'') in the [[wiki:debianmailserver#Wireguard|wireguard]] section below to the server.  There is nothing sensitive in those files yet.\\ ''%%wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=0' -O wg0%%''\\ ''%%wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=1' -O wg0.up%%''\\ ''%%wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=2' -O wgnetgen%%''   - Transfer (''%%wget%%'' on the server) the wireguard interface configuration (''%%/etc/network/interfaces.d/wg0%%'')), the ifup helper script (''%%/etc/wireguard/wg0.up%%''), and setup script (''%%wgnetgen%%'') in the [[wiki:debianmailserver#Wireguard|wireguard]] section below to the server.  There is nothing sensitive in those files yet.\\ ''%%wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=0' -O wg0%%''\\ ''%%wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=1' -O wg0.up%%''\\ ''%%wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=2' -O wgnetgen%%''
   - Over your server's remote console, edit your WireGuard ''%%wgnetgen%%'' script to add the public key from step one, and edit the other parameters as required.  Run the script to generate the wireguard keymat and peer (client) configuration files, but don't look at them.  Don't ''%%cat%%'' or edit any of it except ''%%INITIAL.conf%%'' That is the template for your workstation.  Combine the settings in ''%%INITIAL.conf%%'' with the private key you made in step one and use it to help you finish your initial workstation client configuration.     - Over your server's remote console, edit your WireGuard ''%%wgnetgen%%'' script to add the public key from step one, and edit the other parameters as required.  Run the script to generate the wireguard keymat and peer (client) configuration files, but don't look at them.  Don't ''%%cat%%'' or edit any of it except ''%%INITIAL.conf%%'' That is the template for your workstation.  Combine the settings in ''%%INITIAL.conf%%'' with the private key you made in step one and use it to help you finish your initial workstation client configuration.  
   - Bring up wireguard on the server, reboot the server and connect to its wireguard using the temporary initial config on your workstation.   - Bring up wireguard on the server, reboot the server and connect to its wireguard using the temporary initial config on your workstation.
-  - Enable ssh on the server, and connect to it from your workstation using the server's wireguard IP address.+  - **Properly** configure SSH on the server [[wiki:debianmailserver#SSH|as per the guide below]]then enable it. Connect to it from your workstation using the server's wireguard IP address.
   - Transfer (using ''%%scp%%'') the permanent wireguard configuration for your workstation to the workstation - this config has your workstation's (semi-)permanent pre-shared key.   - Transfer (using ''%%scp%%'') the permanent wireguard configuration for your workstation to the workstation - this config has your workstation's (semi-)permanent pre-shared key.
   - Disconnect from ssh, disconnect from wireguard, and on your workstation configure wireguard to use the new .conf.   - Disconnect from ssh, disconnect from wireguard, and on your workstation configure wireguard to use the new .conf.
-  - Connect your workstation to the server with wireguard using the new config.  Connect with ssh over wireguard.  +  - Connect your workstation to the server with wireguard using the new config.  Connect with ssh over wireguard. Your server and this connection to it is as secure as you can make it remotely.  Now transfer all the remaining devices configurations off to your workstation.
- Your server and this connection to it is as secure as you can make it remotely.  Now transfer all the remaining devices configurations off to your workstation.+
   - Now edit ''/etc/wireguard/wg0'' and remove the temporary config entry from the bottom.   - Now edit ''/etc/wireguard/wg0'' and remove the temporary config entry from the bottom.
  
Line 88: Line 92:
  
 ==== WireGuard ==== ==== WireGuard ====
-We avoid using wg-quick in this setup. Wireguard is an interface, so we will employ the normal Debian method of bringing up an interface.  Namely, adding a definition to /etc/network/interfaces.d/wg0 +We avoid using wg-quick in this setup. Wireguard is an interface, so we will employ the normal Debian method of adding an interface.  Namely, adding a definition to /etc/network/interfaces.d/wg0
- +
-The example below assumes a network on ++10.30.1.0/24.  |**(**//Some people think it's a security risk to re-use sample private IP addresses, and this is technically true for some definitions of "risk" Feel free to use the example, or edit to suit.  I personally tend to use addresses in a 10.X.Y.0/24 address space for server VPNs and in 192.168.X.0/24 range for home, but use whatever system makes sense for you.//**)**+++
  
   $ sudo apt-get install wireguard-tools iptables-nft   $ sudo apt-get install wireguard-tools iptables-nft
 +  $ wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=0' -O wg0
 +  $ sudo cp wg0 /etc/network/interfaces.d/wg0
   $ sudo joe /etc/network/interfaces.d/wg0   $ sudo joe /etc/network/interfaces.d/wg0
 ++++ /etc/network/interfaces.d/wg0 | ++++ /etc/network/interfaces.d/wg0 |
Line 104: Line 108:
 iface wg0 inet static iface wg0 inet static
  
- # static IP address on a /24+ # static IP address of server on a /24
  address 10.30.1.1/24  address 10.30.1.1/24
  
Line 120: Line 124:
  
 </code> </code>
-Make sure you edit the address to reflect what you want for your network. 
 ++++ ++++
-You can see the ++marker tag | //(When I did this the first time, I just edited all my config files bare-bones.  It wasn't until I did my first upgrade a year and a half later that I realized how hard it was to remember exactly what I'd done, and how hard it is to identify changes I had made.  So now I mark every configuration file I make with a signature.  VA1DER, which is me, the hostname of the computer it was made for, and what it's for.  I do the same thing when I add sections to existing config files.  Put something in that's easy to ''%%grep%%'' for.  Also, never touch an existing config file without first ''%%cp -a config.conf config.conf.orig%%''.//) ++I use for all my local config files.+Make sure you edit the address to reflect what you want for your network. The examples here assume a network on ++10.30.1.0/24.| **(**//Some people think it's a security risk to re-use sample private IP addresses, and this is technically true for some definitions of "risk" Feel free to use the example, or edit to suit.  I personally tend to use addresses in a 10.X.Y.0/24 address space for server VPNs and in 192.168.X.0/24 range for home networks, but use whatever system makes sense for you.//**)**++ Make sure any change you make above is reflected below. 
 + 
 +Also, of course, edit the header signature to ++reflect your system | //(When I did this the first time, all of my config files we bare-bones.  No signatures, no comments.  It wasn't until I performed my first upgrade a year and a half later that I realized how hard it was to remember exactly what I'd done, and how hard it is to identify changes I had made.  Sometimes even recognizing my own configurations apart from system ones was difficult.  So now I mark every configuration file I make with a signature.  VA1DER, which is me, the hostname of the computer it was made for, and what it's for.  I do the same thing when I add sections to existing config files.  Put something in that's easy to ''%%grep%%'' for.  Also, never touch an existing config file without first ''%%cp -a config.conf config.conf.orig%%''.//)++
  
 The above interface definition references a post-up script for making sure everything is forwarding properly.  This is stored as ''%%/etc/wireguard/wg0.up%%'': The above interface definition references a post-up script for making sure everything is forwarding properly.  This is stored as ''%%/etc/wireguard/wg0.up%%'':
 +  $ wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=1' -O wg0.up
 +  $ sudo cp wg0.up /etc/wireguard/wg0.up
   $ sudo joe /etc/wireguard/wg0.up   $ sudo joe /etc/wireguard/wg0.up
   $ sudo chmod 755 /etc/wireguard/wg0.up   $ sudo chmod 755 /etc/wireguard/wg0.up
Line 134: Line 141:
 IPT="/sbin/iptables" IPT="/sbin/iptables"
  
-IN_IFACE="eth0"                   # NIC connected to the internet +IN_IFACE="eth0"                   # Server'internet-facing interface name 
-WG_IFACE="wg0"                    # WG NIC +WG_IFACE="wg0"                    # WireGuard interface name 
-SUB_NET="10.8.30.0/24"            # WG IPv4 sub/net aka CIDR +SUB_NET="10.8.30.0/24"            # WireGuard network in CIDR 
-WG_PORT="51820"                   # WG udp port+WG_PORT="51820"                   # WireGuard UDP port number
  
 # Delete old rules, just in case # Delete old rules, just in case
Line 156: Line 163:
 </code> </code>
  
-Make sure you set IN_IFACE to the name of your main internet interface.  The other params need to be consistent with your interface file.  Using port 51820 is recommended - this keeps your wireguard traffic on the same port lots of people use so it doesn't stand out.+Make sure you set IN_IFACE to the name of your main internet interface you see in ''%%ifconfig%%'' or ''%%ip addr show%%''.  The other params need to be consistent with your ''%%/etc/network/interfaces.d/wg0%%'' interface file.  Using port 51820 is recommended - this keeps your wireguard traffic on the same port lots of people use so it doesn't stand out.
 ++++ ++++
  
- +Next you'll generate the WireGuard keymat.  Here's a script for you to run on the server to generate keys and the config files for the server and clients:
-Next generate the keymat.  For this just ''%%sudo su -%%'' and operate as root.  Make an admin folder and a wg0 subfolder to hold your keys and device configuration files. +
-  $ sudo su - +
-  # cd ~ +
-  # mkdir -p admin/wg0 +
-  # cd admin/wg0 +
-Here's a script for you to generate keys and config files:+
 ++++ /root/admin/wg0/wgnetgen | ++++ /root/admin/wg0/wgnetgen |
 <code bash /root/admin/wg0/wgnetgen> <code bash /root/admin/wg0/wgnetgen>
Line 198: Line 199:
  
   # Generate the keys and save them   # Generate the keys and save them
 +  touch "$A"_$HOST.key "$A"_$HOST.psk
 +  chmod g-rwx,o-rwx "$A"_$HOST.key "$A"_$HOST.psk
   wg genkey | tee "$A"_$HOST.key | wg pubkey > "$A"_$HOST.pub 2> /dev/null   wg genkey | tee "$A"_$HOST.key | wg pubkey > "$A"_$HOST.pub 2> /dev/null
   wg genpsk > "$A"_$HOST.psk 2> /dev/null   wg genpsk > "$A"_$HOST.psk 2> /dev/null
Line 205: Line 208:
   if [ $A -eq 1 ]; then # The first host is the "server"   if [ $A -eq 1 ]; then # The first host is the "server"
     # Make the [Interface] section for the server     # Make the [Interface] section for the server
 +    touch $INTERFACE.conf
 +    chmod g-rwx,o-rwx $INTERFACE.conf
     printf "# $SERVER wireguard configuration for $INTERFACE\n\n# Our private key and port\n[Interface]\nPrivateKey = %s\nListenPort = $PORT\n\n# Sections for our peers (really our clients)\n\n" $(cat "$A"_$HOST.key) > $INTERFACE.conf     printf "# $SERVER wireguard configuration for $INTERFACE\n\n# Our private key and port\n[Interface]\nPrivateKey = %s\nListenPort = $PORT\n\n# Sections for our peers (really our clients)\n\n" $(cat "$A"_$HOST.key) > $INTERFACE.conf
     rm "$A"_$HOST.psk   # We don't actually need or want a preshared key for the server     rm "$A"_$HOST.psk   # We don't actually need or want a preshared key for the server
Line 212: Line 217:
     printf "# $HOST\n[Peer]\nPublicKey = %s\nPresharedKey = %s\nAllowedIPs = $NETPREFIX$(expr $A + 0)/32\nPersistentKeepalive = 25\n\n" $(cat "$A"_$HOST.pub) $(cat "$A"_$HOST.psk) >> $INTERFACE.conf     printf "# $HOST\n[Peer]\nPublicKey = %s\nPresharedKey = %s\nAllowedIPs = $NETPREFIX$(expr $A + 0)/32\nPersistentKeepalive = 25\n\n" $(cat "$A"_$HOST.pub) $(cat "$A"_$HOST.psk) >> $INTERFACE.conf
     # Also generate a config file for the peer itself     # Also generate a config file for the peer itself
-    printf "# WireGuard configuration for $HOST\n\n[Interface]\nPrivateKey = %s\nAddress = $NETPREFIX$(expr $A + 0)/32\nDNS = $DNS\n\n[Peer]\nPublicKey = %s\nPresharedKey = %s\nAllowedIPs = $NETPREFIX""0/24\nEndPoint = $SERVER\nPersistentKeepalive = 25\n"\+    printf "# WireGuard configuration for $HOST\n\n[Interface]\nPrivateKey = %s\nAddress = $NETPREFIX$(expr $A + 0)/24\nDNS = $DNS\n\n[Peer]\nPublicKey = %s\nPresharedKey = %s\nAllowedIPs = $NETPREFIX""0/24\nEndPoint = $SERVER:$PORT\nPersistentKeepalive = 25\n"\
             $(cat "$A"_$HOST.key) $(cat 01_$SERVERHOST.pub) $(cat "$A"_$HOST.psk) > "$A"_$HOST.conf             $(cat "$A"_$HOST.key) $(cat 01_$SERVERHOST.pub) $(cat "$A"_$HOST.psk) > "$A"_$HOST.conf
   fi   fi
Line 219: Line 224:
 done done
  
-# Add a temporary peer to the configuration file for use with the initial connection+# Add a tempoary peer to the configuration file for use with the initial connection
 printf "# TEMPORARY peer for the initial connection\n[Peer]\nPublicKey = $PUBTEMP\nAllowedIPs = $NETPREFIX""200/32\nPersistentKeepalive = 25\n" >> $INTERFACE.conf printf "# TEMPORARY peer for the initial connection\n[Peer]\nPublicKey = $PUBTEMP\nAllowedIPs = $NETPREFIX""200/32\nPersistentKeepalive = 25\n" >> $INTERFACE.conf
  
 # Create a temporary peer configuration template.  This doesn't have the private key, that never leaves the workstation. # Create a temporary peer configuration template.  This doesn't have the private key, that never leaves the workstation.
 printf "# Wireguard TEMPORARY configuration for one workstation. Use this as a\n# template to set up wireguard on the workstation for an initial connection.\n# Use the private key generated on the workstation.\n\n" > INITIAL.conf printf "# Wireguard TEMPORARY configuration for one workstation. Use this as a\n# template to set up wireguard on the workstation for an initial connection.\n# Use the private key generated on the workstation.\n\n" > INITIAL.conf
-printf "[Interface]\nPrivateKey = <workstationkey>\nAddress = $NETPREFIX""200/32\nDNS = $DNS\n\n[Peer]\nPublicKey = %s\nAllowedIPs = $NETPREFIX""0/24\nEndPoint = $SERVER\nPersistentKeepalive = 25\n"\+printf "[Interface]\nPrivateKey = <workstationkey>\nAddress = $NETPREFIX""200/32\nDNS = $DNS\n\n[Peer]\nPublicKey = %s\nAllowedIPs = $NETPREFIX""0/24\nEndPoint = $SERVER:$PORT\nPersistentKeepalive = 25\n"\
        $(cat 01_$SERVERHOST.pub) >> INITIAL.conf        $(cat 01_$SERVERHOST.pub) >> INITIAL.conf
 #end. #end.
Line 230: Line 235:
 </code> </code>
 ++++ ++++
-The ''%%wgnetgen%%'' script needs to be edited with your configuration.  For it you need: + 
-  - network address +For this part just ''%%sudo su -%%'' and operate as root.  Make an admin folder and a wg0 subfolder to hold your keys and device configuration files. 
-  - The list of hosts/devices that you are generating for.  You might think of making extras for future devices+ 
-  - The full hostname of your server.  If it doesn't yet have one reachable over the internet, substitute its ip address.+  $ sudo su - 
 +  # cd ~ 
 +  # mkdir -p admin/wg0 
 +  # cd admin/wg0 
 +  
 +The ''%%wgnetgen%%'' script needs to be edited with your configuration.  You will need: 
 +  - The network part of the private IP you chose in the interface config. 
 +  - The list of hosts/devices that you are generating client configurations for.  You might want one for your watchdog device, and maybe a few extras for future expansion
 +  - The full (FQDN) hostname of your server.  If it doesn't yet have one reachable over the internet, substitute its static ip address.
   - Port number, same as in ''%%wg0.up%%''   - Port number, same as in ''%%wg0.up%%''
-  - A DNS server.  This is only really needed if you decide to use this wireguard link as a full-traffic VPN for any devices.  Use your server's upstream DNS, or any public one you like. +  - A DNS server.  This is only really needed if you decide to use this WireGuard link as a full-traffic VPN for any devices.  Use your server's upstream DNS, or any public one you like. 
-  - A temporary public wireguard key for your workstation.  For Windows you can click "Add Empty Tunnel" and it will generate one In Linux: <code>$ wg genkey | tee TEMP.key | wg pubkey > TEMP.pub</code>+  - The public key from the temporary WireGuard tunnel you made in [[wiki:debianmailserver#SSH over WireGuard Remote Server Procedure|step 1 above]].  If you haven't made it yet then:\\ For ++Windows| bring up WireGuard's window from the task tray, click the ↓ symbol beside "Add tunnel" and select "Add empty tunnel…"Give it a temporary name, copy the public key off, and save it++\\ For ++Linux|''%%$ wg genkey | tee TEMPORARY.key | wg pubkey > TEMPORARY.pub && cat TEMPORARY.pub%%''\\ The above will generate the private and public keys and print the public one.  You'll have to use the private key to set up your temporary tunnel in Network Manager or whatever your distribution's method is.++ 
 + 
 +  # wget 'https://wiki.va1der.net/doku.php/wiki:debianmailserver?do=export_code&codeblock=2' -O wgnetgen
   # joe wgnetgen   # joe wgnetgen
 +  # chmod +x wgnetgen
   # ./wgnetgen   # ./wgnetgen
-At this point, don't actually look at any of the keymat.  Don't edit or look at ''%%wg0.conf%%'' If you do look at it (to make sure the script is operating as it should and/or to check your values) then re-run the script again after to generate new keymat and then use the regenerated  ''%%wg0.conf%%'' The only file you should look at is INITIAL.conf, and use that to help you configure your workstation's wireguard.+At this point, don't actually look at any of the keymat.  Don't edit or even look at ''%%wg0.conf%%'' If you do look at it (to make sure the script is operating as it should and/or to check your values) then re-run the script again after to generate new keymat and then use the regenerated ''%%wg0.conf%%''.  You want to make your connection as secure as it can be before moving any keymat over it.  The only file you should look at is INITIAL.conf.
   # cp ./wg0.conf /etc/wireguard   # cp ./wg0.conf /etc/wireguard
   # cat INITIAL.conf   # cat INITIAL.conf
 +Use the settings in INITIAL.conf to help you configure your workstation's initial temporary WireGuard tunnel to the server.
  
 Before you reboot, check to make sure that ''%%/etc/network/interfaces%%'' is set to read the files in ''%%/etc/network/interfaces.d/%%'' The first line should be ''%%source-directory /etc/network/interfaces.d/%%'' or ''%%source /etc/network/interfaces.d/*%%'' Before you reboot, check to make sure that ''%%/etc/network/interfaces%%'' is set to read the files in ''%%/etc/network/interfaces.d/%%'' The first line should be ''%%source-directory /etc/network/interfaces.d/%%'' or ''%%source /etc/network/interfaces.d/*%%''
  
-Once you reboot, your wireguard adapter should be up.  You can verify with ''%%wg%%'' and ++ifconfig. | ''%%$ sudo apt-get install net-tools%%''+++Once you reboot, your wireguard adapter should be up. You can verify with ''%%wg%%'' and ++ifconfig. | ''%%$ sudo apt-get install net-tools%%''++
   $ sudo wg   $ sudo wg
   $ sudo ifconfig   $ sudo ifconfig
Line 251: Line 268:
   $ sudo iptables -L -n --line-numbers -v   $ sudo iptables -L -n --line-numbers -v
      
-The above can help you diagnose issues if you have troubles connecting.  Once you successfully connect with your temporary wireguard config from your workstation, you can then turn on SSH in the server, ''%%ssh%%'' to it, and get your permanent workstation config file (with its preshared key) off it and configure your workstation'wireguard to use it.  Once that is done and you're ''%%ssh%%''ing over that, you can get the rest of your device keys and/or config files off and configure the rest of your devices.  Remember to use secure means to transfer those configurations to your devices.  A sneaker-net is your friend here. +Try and connect your workstation's initial temporary tunnel.  The above can help you diagnose issues if you have troubles connecting.  Once you successfully connect with your temporary wireguard config from your workstation, you can then set up SSH on the server (see below). 
 + 
 +Once SSH is properly configured and runningthen ''%%ssh%%'' from your workstation to the server using the server's WireGuard address. Use this connection to ''%%scp%%'' your workstation's permanent WireGuard config file (with its preshared key) off it and configure your workstation'WireGuard to use it.  Once that is done and you're connected over ''%%ssh%%'' that is over your permanent WireGuard configthen you can get the rest of your device keys and/or config files off and configure the rest of your devices.  Remember to use secure means to transfer those configurations to your devices.  A sneaker-net is your friend here. 
  
 ==== SSH ==== ==== SSH ====
Line 364: Line 383:
   $ sudo veracrypt -c --pim=1 --size=10G --filesystem=none --volume-type=normal /media/aegis.img   $ sudo veracrypt -c --pim=1 --size=10G --filesystem=none --volume-type=normal /media/aegis.img
 VeraCrypt will ask: VeraCrypt will ask:
-  * **Encryption Algorithm:**\\ The suggestion algorithm is #2, Serpent.  Though if your VPS provides AES-NI instructions then algorithm #13, Serpent(AES) will add AES to that at almost no cost. +  * {{ :wiki:debian12mail_veracryptformat.png?direct&400|}}**Encryption Algorithm:**\\ The suggestion algorithm is #2, Serpent.  Though if your VPS provides AES-NI instructions then algorithm #13, Serpent(AES) will add AES to that at almost no cost. 
   * **Hash Algorithm:**\\ Algo #3, ++Blake2s|**(**//Blake2s is a relatively new algorithm that adapts the chacha20 symmetric encryption cipher into a hash.//**)**++, is recommended.  SHA-512 and SHA-256 are both solid choices too, but not as fast.   * **Hash Algorithm:**\\ Algo #3, ++Blake2s|**(**//Blake2s is a relatively new algorithm that adapts the chacha20 symmetric encryption cipher into a hash.//**)**++, is recommended.  SHA-512 and SHA-256 are both solid choices too, but not as fast.
   * **Password:**\\ Use a proper password manager (KeePassXC or something similar) to generate your password.  Create one that has at least 256 bits of entropy, so on the order of 44 characters in length.  A password of sufficient entropy eliminates the need for a [[https://veracrypt.eu/en/Personal%20Iterations%20Multiplier%20%28PIM%29.html|PIM]].   * **Password:**\\ Use a proper password manager (KeePassXC or something similar) to generate your password.  Create one that has at least 256 bits of entropy, so on the order of 44 characters in length.  A password of sufficient entropy eliminates the need for a [[https://veracrypt.eu/en/Personal%20Iterations%20Multiplier%20%28PIM%29.html|PIM]].
Line 384: Line 403:
  
 ==== Syncthing ==== ==== Syncthing ====
-Syncthing is employed to signal to the watchdog computer when the server has rebooted and needs assistance mounting the above encrypted storage. Syncthing is something that's useful to have on the server anyway, as a means of quickly and easily transferring configuration files on and off.  It is moderately secure, but without ++extra measures| **(**//Syncthing's security can be improved by forcing it to use WireGuard, but this will require the watchdog computer to be added to the WireGuard network.  That isn't a bad thing at all, though, so feel free.  It can also be forced into a hub-and-spoke star topology where directory encryption is used as a sort of poor-man's pre-shared key, but that requires one node to be untrusted and not able to easily access the files being shared. +Syncthing is employed to signal to the watchdog computer when the server has rebooted and needs assistance mounting the above encrypted storage. Syncthing is also something that's useful to have on the server anyway, as a means of quickly and easily transferring configuration files on and off.  It is moderately secure, but without ++extra measures| **(**//Syncthing's security can be improved by forcing it to use WireGuard, but this will require the watchdog computer to be added to the WireGuard network.  That isn't a bad thing at all, though, so feel free.  It can also be forced into a hub-and-spoke star topology where directory encryption is used as a sort of poor-man's pre-shared key, but that requires one node to be untrusted and not able to easily access the files being shared. 
  Either or both these extra measures are left as an exercise for the reader.//**)**++ it should **not** be trusted with keymat or anything really sensitive.  Either or both these extra measures are left as an exercise for the reader.//**)**++ it should **not** be trusted with keymat or anything really sensitive.
  
Line 397: Line 416:
 Look for the line ''%%<gui enabled="true" tls="false" debugging="false">%%'' and change the next line from ''%%<address>127.0.0.1:8384</address>%%'' to ''%%<address>10.30.1.1:8384</address>%%'' (or whatever you set your server's WireGuard address to).  Then restart the service: Look for the line ''%%<gui enabled="true" tls="false" debugging="false">%%'' and change the next line from ''%%<address>127.0.0.1:8384</address>%%'' to ''%%<address>10.30.1.1:8384</address>%%'' (or whatever you set your server's WireGuard address to).  Then restart the service:
   $ sudo service syncthing@<user> restart   $ sudo service syncthing@<user> restart
-Now you can navigate a browser to: ''%%http://10.30.1.1:8384/%%'' and you should see the Syncthing GUI.+Now you can navigate a browser to: ''%%http://10.30.1.1:8384/%%'' (or whatever you set the server's GUI listen address to) and you should see the Syncthing GUI.
   - You'll be asked whether you want to enable anonymous usage reporting.  This is a production server, so it's recommended to turn that off.  You'll also be asked to set the GUI authentication password, which you should do.   - You'll be asked whether you want to enable anonymous usage reporting.  This is a production server, so it's recommended to turn that off.  You'll also be asked to set the GUI authentication password, which you should do.
   - In Actions→Settings→General you can set your server name, and verify the usage reporting you selected.   - In Actions→Settings→General you can set your server name, and verify the usage reporting you selected.
Line 407: Line 426:
 ==== Syncthing (on Watchdog)==== ==== Syncthing (on Watchdog)====
  
-Setting up Syncthing on the watchdog device depends on the type of device.  If you have a Debian or Raspbian based device, then setup will be similar to the server.  If you use OpenWRT, or a device that supports [[https://entware.net/|entware]], then the following method and supporting scripts can be used almost directly.+The method for setting up Syncthing on your watchdog device depends on the type of device.  If you have a Debian or Raspbian based device, then setup will be similar to the server.  If you use OpenWRT, or a device that supports [[https://entware.net/|entware]], then the following method and supporting scripts can be used almost directly.
  
 In OpenWRT you can install Syncthing and some of the other utilities the following scripts will need with: In OpenWRT you can install Syncthing and some of the other utilities the following scripts will need with:
Line 422: Line 441:
 # Make sure you open up the port for syncthing in the firewall settings # Make sure you open up the port for syncthing in the firewall settings
  
-# Recommend full OpenWRT nuhup package for this: 'opkg install coreutils-nohup'+# Recommend OpenWrt'full-featured nuhup package for this: 'opkg install coreutils-nohup'
  
 # Base dir for where the Syncthing config folder and logs will go - be mindful # Base dir for where the Syncthing config folder and logs will go - be mindful
Line 436: Line 455:
 </code> </code>
 ++++ ++++
-You will need to ensure the directory structure used in the script exists (the above ''%%ststart%%'' script uses ''%%/root/admin/etc/syncthing/%%'').  As noted in the script, be mindful of the type of storage your device has and, if possible, consider using ++USB or sdcard storage locations. | **(**//On all my OpenWRT devices I make my whole /root user folder a softlink to a permanently mounted sdcard or usb device to eliminate wear on irrepaceable internal device storage.//**)**+++Ensure the directory structure used in the script exists (the above ''%%ststart%%'' script uses ''%%/root/admin/etc/syncthing/%%'').  Be mindful of the type of storage your device has and, if possible, consider using ++USB or sdcard storage locations. | **(**//On all my OpenWRT devices I make my whole /root user folder a softlink to a permanently mounted sdcard or USB device to eliminate wear on irreplaceable internal device storage.//**)**++
  
 Since your whole server restart mechanism fails if the watchdog's Syncthing fails, a little cron job script to periodically check it is a good idea: Since your whole server restart mechanism fails if the watchdog's Syncthing fails, a little cron job script to periodically check it is a good idea:
Line 477: Line 496:
  
  
-The first time you run syncthing it will generate its config file. Be default syncthing only listens to GUI connections on localhost.  If you're using a smaller device, you won't have a web browser on it to connect.  So you will at least need to open it up to a) your device's local lan address, or b) your device's wireguard address (if you attach it to the server's wireguard.  Don't open it up to the world (0.0.0.0), even if it's sitting safely inside your firewall.+The first time you run Syncthing it will generate its config file. Be default Syncthing only listens to GUI connections on localhost.  If you're using a smaller device, you won't have a web browser on it to connect with.  You'll need to allow GUI connections from a) your device's local LAN address, or b) your device's wireguard address (if you attach it to the server's wireguard.  Don't open it up to the world (0.0.0.0), even if it's sitting safely inside your firewall.
   # joe /root/admin/etc/syncthing/config.xml   # joe /root/admin/etc/syncthing/config.xml
 Look for the line ''%%<gui enabled="true" tls="false" debugging="false">%%'' and change the next line from ''%%<address>127.0.0.1:8384</address>%%'' to whatever your decide above. Look for the line ''%%<gui enabled="true" tls="false" debugging="false">%%'' and change the next line from ''%%<address>127.0.0.1:8384</address>%%'' to whatever your decide above.
 +  # killall syncthing
 +  # /root/bin/ststart
 +
 +Now you can navigate a browser to ''%%http://<watchdogui>:8384/%%'' (whatever you set the watchdog's GUI listen address to) and you should see the Syncthing GUI:
 +  - {{ :wiki:debian12mail_syncthingpriv.png?direct&600|Privileged user warning}}The first time you connect to the GUI, it will give you the same notifications you had on the server asking for permission to phone home and to change the GUI password.  It will also complain about being run as root. There will be op open ports on this installation and OpenWrt has limited support for non-root anyway, so you can ignore this warning.
 +  - In Actions→Settings→General you can set your watchdog device's name, and verify usage reporting is as you selected it.
 +  - On the Connections tab you'll see checkboxes for “Enable NAT traversal”, “Global Discovery”, “Local Discovery” and “Enable Relaying”. Turn them all off.
 +  - Also on the connections tab, clear the **Sync Protocol Listen Addressses** textbox - delete the word ''%%default%%''
 +  - In Actions→Advanced→Options you'll see “Enable Crash Reporting”. This is also a good thing to turn off.
 +  - The default shared folder will likely be in ''%%/root/Sync%%'' This is reasonable, but you should again be mindful of wear on your device's non-volatile storage - ''%%/root/Sync%%'' should be located somewhere on a USB or sdcard storage.  You can't move a Syncthing folder location after it's been created - you have to remove it and re-ad it.  Or, stop Syncthing, move the folder, and make the old location a soft-link to it.
 +
 +You can connect your watchdog's Syncthing to the server's.
 +  - Navigate another browser tab to the server's Syncthing and select Actions→Show ID, click "Copy"
 +  - Go back to the watchdog's Syncthing, select Add Remote Device
 +  - Paste in the device ID from above.  You can fill in the server's Syncthing name or, if you leave it blank, it will pick up the name from the server.
 +  - Go to the Advanced tab.  You need to enter the server's listen address here.  If the watchdog device is on the server's WireGuard network, then you can use the server's WireGuard address.  This will add extra security for Syncthing but isn't required.  You can use the server's public hostname/IP address, and Syncthing will still be ++moderately secure |**(**//**"moderately secure"** = secure enough for our server reboot signaling and casual use moving scripts and files, but **not** secure enough to, say, transfer keymat//**)**++  For the address delete ''%%dynamic%%'' and enter: ''%%quic4://<serveraddress>:22000%%''
 +  - {{ :wiki:debian12mail_syncthingnewdevice.png?direct&600|New Device Request}}Go to the server's Syncthing GUI browser tab.  You should see a new device connection request there.  Check to make sure the device ID matches the watchdog's Syncthing ID and then select **Add Device**.
 +  - Click on the **Sharing** tab, make sure introducer and auto-accept are turned off, click to check the ''%%Sync%%'' folder, and click **Save**.
 +  - Return to the watchdog devices Syncthing GUI browser tab.  You should get a notification that the server wants to share the ''%%Sync%%'' folder.  Accept.
 +
 +And now your watchdog and server have linked folders ''%%/home/<user>/Sync%%'' on the server should now mirror ''%%/root/Sync%%'' on the watchdog device.
 +
 +==== Reboot Signalling ====
 +
 +Now that we've gone through the pain of linking folders between the server and watchdog, signaling the watchdog when the server reboots is pretty painless.  On the server:
 +
 +  # mkdir Sync/etc
 +  # echo 0 > Sync/etc/<SERVERNAME>RebootFlag
 +  # sudo crontab -e
 +
 +Add this to the crontab:
 +  @reboot              sleep 30 && echo 1 > /home/<username>/Sync/etc/<SERVERNAME>RebootFlag
 +
 +Now every time the server reboots, it will write a 1 to the file, which Syncthing will transfer over to the watchdog.
 +
 +==== Encrypted Container Remote Mount ====
 +
 +The whole purpose of the watchdog is to enable it to mount the server's encrypted container when the server reboots.  We're going to do this with SSH.  The password for the encrypted container and also the sudo password for a sudo-capable user (it might as well be your main user) are both going to be sent over SSH.  Put them in files on the watchdog:
 +  # touch /root/admin/etc/<SERVERNAME>_container /root/admin/etc/<SERVERNAME>_control
 +  # chmod 600 /root/admin/etc/<SERVERNAME>_container /root/admin/etc/<SERVERNAME>_control
 +  # joe /root/admin/etc/<SERVERNAME>_container
 +  # joe /root/admin/etc/<SERVERNAME>_control
 +Make sure each file consists of the exact password and one newline.  Nothing else.
 +
 +The server name used for subsequent examples will be "QRO" Make sure you change accordingly.
 +
  
 ====== References ====== ====== References ======
wiki/debianmailserver.1724442708.txt.gz · Last modified: 2024/08/23 19:51 by va1der