Skip to content

Commit

Permalink
Split the daemon into network and firewall part
Browse files Browse the repository at this point in the history
  • Loading branch information
mbuesch committed Jul 24, 2024
1 parent d0d4e06 commit 60a0a33
Show file tree
Hide file tree
Showing 29 changed files with 1,528 additions and 113 deletions.
52 changes: 52 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
members = [
"letmein",
"letmein-conf",
"letmein-fwproto",
"letmein-proto",
"letmein-seccomp",
"letmein-systemd",
"letmeind",
"letmeinfwd",
]
resolver = "2"

Expand All @@ -24,6 +27,7 @@ keywords = [ "port-knocking", "port", "knock", "firewall", "nftables" ]

[workspace.dependencies]
anyhow = "1"
autocfg = "1"
clap = "4"
getrandom = "0.2"
hickory-proto = "0.24"
Expand All @@ -32,12 +36,16 @@ hmac = "0.12"
libc = "0.2"
nftables = "0.4"
sd-notify = "0.4"
seccompiler = "0.4"
sha3 = "0.10"
subtle = "2"
tokio = "1"
user_lookup = { version = "0.3", default-features = false }

letmein-conf = { version = "2", path = "./letmein-conf" }
letmein-fwproto = { version = "2", path = "./letmein-fwproto" }
letmein-proto = { version = "2", path = "./letmein-proto" }
letmein-seccomp = { version = "2", path = "./letmein-seccomp" }
letmein-systemd = { version = "2", path = "./letmein-systemd" }

[profile.release]
Expand Down
50 changes: 32 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,43 +138,45 @@ After installing all build prerequisites, run the build script:

## Installing letmein

### Install server
### Install client

After building, run the `install-server.sh` to install the letmeind server to `/opt/letmein/`:
Then run the `install-client.sh` to install the letmein client to `/opt/letmein/`:

```sh
./install-server.sh
./install-client.sh
```

Installing the server will also install the service and socket into systemd and start the letmeind server.
The client is used to send a knock packet to the server.

The server is used to receive knock packets from the client.
Upon successful knock authentication, the server will open the knocked port in its `nftables` firewall.
### Install server

### Install client
#### Prepare user and group for the server

Then run the `install-client.sh` to install the letmein client to `/opt/letmein/`:
The public network facing part of the letmein server runs with reduced privileges to reduce the attack surface.

For this to work, the system user `letmeind` and a system group `letmeind` have to be present in `/etc/passwd` and `/etc/group`

You can use the following helper script to create the user and group in your system:

```sh
./install-client.sh
./create-user.sh
```

The client is used to send a knock packet to the server.
#### Install the server and systemd units

## Security notice: User identifiers and resource identifiers
After building and creating the `letmeind` system user, run the `install-server.sh` to install the letmeind server to `/opt/letmein/`:

Please be aware that the user identifiers and resource identifiers from the configuration files are transmitted over the network without encryption in clear text.
```sh
./install-server.sh
```

Make sure the user identifiers and resource identifiers do **not** include any private information.
Installing the server will also install the service and socket into systemd and start the letmeind server.

These identifiers are merely meant to be an abstract identification for managing different `letmein` keys, installations and setups.
The server is used to receive knock packets from the client.
Upon successful knock authentication, the server will open the knocked port in its `nftables` firewall.

## Platform support

### Server

The server application `letmeind` is Linux-only, because it only supports `nftables` as firewall backend.

### Client

The client application `letmein` is portable and should run on all major platforms.
Expand All @@ -185,6 +187,18 @@ Tested platforms are:
- Windows
- MacOS (build tested only)

### Server

The server application `letmeind` is Linux-only, because it only supports `nftables` as firewall backend.

## Security notice: User identifiers and resource identifiers

Please be aware that the user identifiers and resource identifiers from the configuration files are transmitted over the network without encryption in clear text.

Make sure the user identifiers and resource identifiers do **not** include any private information.

These identifiers are merely meant to be an abstract identification for managing different `letmein` keys, installations and setups.

## Internals and design goals

The main design goals of letmein are:
Expand Down
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ cargo auditable build --release || die "Cargo build (release) failed."
cargo audit bin --deny warnings \
target/release/letmein \
target/release/letmeind \
target/release/letmeinfwd \
|| die "Cargo audit failed."
check_dynlibs target/release/letmein
check_dynlibs target/release/letmeind
check_dynlibs target/release/letmeinfwd

# vim: ts=4 sw=4 expandtab
76 changes: 76 additions & 0 deletions create-user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/sh
# -*- coding: utf-8 -*-

info()
{
echo "--- $*"
}

error()
{
echo "=== ERROR: $*" >&2
}

warning()
{
echo "=== WARNING: $*" >&2
}

die()
{
error "$*"
exit 1
}

entry_checks()
{
[ "$(id -u)" = "0" ] || die "Must be root to create users."
}

sys_groupadd()
{
local args="--system"
info "groupadd $args $*"
groupadd $args "$@" || die "Failed groupadd"
}

sys_useradd()
{
local args="--system -s /usr/sbin/nologin -d /nonexistent -M -N"
info "useradd $args $*"
useradd $args "$@" || die "Failed useradd"
}

do_usermod()
{
info "usermod $*"
usermod "$@" || die "Failed usermod"
}

stop_daemons()
{
systemctl stop letmeind.socket >/dev/null 2>&1
systemctl stop letmeind.service >/dev/null 2>&1
systemctl stop letmeinfwd.socket >/dev/null 2>&1
systemctl stop letmeinfwd.service >/dev/null 2>&1
}

remove_users()
{
# Delete all existing users and groups, if any.
userdel letmeind >/dev/null 2>&1
groupdel letmeind >/dev/null 2>&1
}

add_users()
{
sys_groupadd letmeind
sys_useradd -g letmeind letmeind
}

entry_checks
stop_daemons
remove_users
add_users

# vim: ts=4 sw=4 expandtab
53 changes: 51 additions & 2 deletions install-server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ do_systemctl()
systemctl "$@" || die "Failed to systemctl $*"
}

do_chown()
{
info "chown $*"
chown "$@" || die "Failed to chown $*"
}

do_chmod()
{
info "chmod $*"
chmod "$@" || die "Failed to chmod $*"
}

try_systemctl()
{
info "systemctl $*"
Expand All @@ -45,19 +57,32 @@ try_systemctl()
entry_checks()
{
[ -d "$target" ] || die "letmein is not built! Run ./build.sh"

[ "$(id -u)" = "0" ] || die "Must be root to install letmein."

if ! grep -qe letmeind /etc/passwd; then
die "The system user 'letmeind' does not exist in /etc/passwd. Please run ./create-user.sh"
fi
if ! grep -qe letmeind /etc/group; then
die "The system group 'letmeind' does not exist in /etc/group. Please run ./create-user.sh"
fi
}

stop_services()
{
try_systemctl stop letmeind.socket
try_systemctl stop letmeind.service
try_systemctl stop letmeinfwd.socket
try_systemctl stop letmeinfwd.service
try_systemctl disable letmeind.service
try_systemctl disable letmeind.socket
try_systemctl disable letmeinfwd.service
try_systemctl disable letmeinfwd.socket
}

start_services()
{
do_systemctl start letmeinfwd.socket
do_systemctl start letmeind.socket
}

Expand All @@ -74,14 +99,37 @@ install_dirs()

install_conf()
{
if ! [ -e /opt/letmein/etc/letmeind.conf ]; then
if [ -e /opt/letmein/etc/letmeind.conf ]; then
do_chown root:letmeind /opt/letmein/etc/letmeind.conf
do_chmod 0640 /opt/letmein/etc/letmeind.conf
else
do_install \
-o root -g root -m 0640 \
-o root -g letmeind -m 0640 \
"$basedir/letmeind/letmeind.conf" \
/opt/letmein/etc/letmeind.conf
fi
}

install_letmeinfwd()
{
do_install \
-o root -g root -m 0755 \
"$target/letmeinfwd" \
/opt/letmein/bin/

do_install \
-o root -g root -m 0644 \
"$basedir/letmeinfwd/letmeinfwd.service" \
/etc/systemd/system/

do_install \
-o root -g root -m 0644 \
"$basedir/letmeinfwd/letmeinfwd.socket" \
/etc/systemd/system/

do_systemctl enable letmeind.socket
}

install_letmeind()
{
do_install \
Expand Down Expand Up @@ -123,6 +171,7 @@ entry_checks
stop_services
install_dirs
install_conf
install_letmeinfwd
install_letmeind
start_services

Expand Down
Loading

0 comments on commit 60a0a33

Please sign in to comment.