Security
We make sure that your Microbolt is secured against unauthorized remote access.
The Microbolt will be visible from the internet and therefore needs to be secured against online attacks using various methods.
Login with SSH keys
One of the best options to secure the sensitive SSH login is to disable passwords altogether and require an SSH key certificate. Only someone with physical possession of the private certificate key can log in.
Preparations on host
system
Create a new public/private key pair
Skip if you already have one
ssh-keygen -t rsa -b 4096
Follow instructions, optionally enter a key passphrase to protect your key, you
can use password [A]
The public key now needs to be copied to the PC
cat ./.ssh/id_rsa.pub |
ssh satoshi@nakamoto01 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Preparations on server
system
It’s also recommended to change default ssh
port 22
, to something else like
2222
Disable password and root logins
sed 's/DROPBEAR_OPTS=""/DROPBEAR_OPTS="-w -s -p 2222"/' /etc/conf.d/dropbear > _
$SU mv -f _ /etc/conf.d/dropbear
Restart service to apply changes
if $SU rc-service dropbear status | grep -q "started"; then
$SU rc-service dropbear restart
elif $SU rc-service sshd status | grep -q "started"; then
$SU rc-service sshd restart
fi
Disable root
account
$SU passwd -l root
Firewall
A firewall controls what kind of outside traffic your machine accepts and which applications can send data out. By default, many network ports are open and listening for incoming connections. Closing unnecessary ports can mitigate many potential system vulnerabilities.
For now, only SSH should be reachable from the outside. Bitcoin Core and LND are using Tor and don’t need incoming ports.
Install awall
$SU apk add awall iptables ip6tables
Load the necessary kernel modules and load them at boot
$SU modprobe -av ip_tables ip6_tables
printf "%s\n" \
"ip_tables" \
"ip6_tables" \
| $SU tee /etc/modules-load.d/awall.conf
Configure and enable the firewall rules
Replace eth0
with your network interface
$SU $EDITOR /etc/awall/optional/base-config.json
{
"description": "Base zones and policies",
"zone": {
"internet": { "iface": "eth0" }
},
"policy": [
{ "in": "internet", "action": "drop" },
{ "out": "internet", "action": "accept" }
]
}
If you changed the SSH port, replace "service": "ssh"
with your new port
"service": { "proto": "tcp", "port": 2222 },
or whatever you chose
$SU $EDITOR /etc/awall/optional/ssh.json
{
"description": "Allow incoming SSH access (TCP/22)",
"filter": [
{
"in": "internet",
"out": "_fw",
"service": "ssh",
"action": "accept",
"conn-limit": { "count": 3, "interval": 60 }
}
]
}
Enable the firewall on boot
$SU rc-update add iptables
$SU rc-update add ip6tables
Start the firewall
$SU awall list
base-config disabled Base zones and policies
ssh disabled Allow incoming SSH access (TCP/22)
$SU awall enable base-config ssh
$SU awall activate
Check if the firewall is properly configured and active
$SU iptables -S | grep 22
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j limit-ssh-0
More: Alpine Wall User’s Guide
How-To: How-To Alpine Wall
If you find yourself locked out by mistake, you can connect a keyboard and screen to your PC to log in locally and fix these settings (especially for the SSH port).
Reverse proxy
Several components of this guide will expose a communication port, for example, the Block Explorer, or the ThunderHub web interface for your Lightning node. Even if you use these services only within your own home network, communication should always be encrypted. Otherwise, any device in the same network can listen to the exchanged data, including passwords.
We use Caddy to encrypt the communication with SSL/TLS (Transport Layer Security). This setup is called a “reverse proxy”: Caddy provides secure communication to the outside and routes the traffic back to the internal service without encryption. Alternatively you can also install nginx to perform the same functions.
We do not recommend using the Caddy available in Alpine because it will conflict when Caddy updates itself to the latest version and adds modules. Also, the provided init script is not as complete as the one proposed in this guide.
Create the caddy user/group
$SU addgroup -S caddy
$SU adduser \
-S \
-D \
-H \
-h /dev/null \
-s /sbin/nologin \
-G caddy \
-g caddy \
caddy
- Add the user satoshi to the group caddy
$SU adduser satoshi caddy
Download latest release
cd /tmp
LATEST=$(wget -qO- https://api.github.com/repos/caddyserver/caddy/releases/latest | grep "tag_name" | cut -d '"' -f 4 | sed 's/^v//')
wget https://github.com/caddyserver/caddy/releases/download/v$LATEST/caddy_${LATEST}_linux_amd64.tar.gz \
https://github.com/caddyserver/caddy/releases/download/v$LATEST/caddy_${LATEST}_checksums.txt
- Checksum check
grep caddy_${LATEST}_linux_amd64.tar.gz caddy_${LATEST}_checksums.txt | sha512sum -c
caddy_${LATEST}_linux_amd64.tar.gz: OK
Extract and install binary
$SU tar xzf caddy_${LATEST}_linux_amd64.tar.gz caddy -C /usr/bin/
- Add necessary modules
$SU caddy add-package github.com/mholt/caddy-l4
Configuration
- First of all, create directories for configuration files
$SU mkdir -p \
/etc/caddy/sites \
/etc/caddy/streams
$SU $EDITOR /etc/caddy/Caddyfile
{
local_certs
ocsp_stapling off
log {
format console
}
layer4 {
import /etc/caddy/streams/*.caddy
}
}
(tls) {
tls internal {
on_demand
}
}
https:// {
import tls
}
import /etc/caddy/sites/*.caddy
Use your own self-signed certificates
$SU openssl req \
-x509 \
-nodes \
-newkey rsa:4096 \
-keyout /path/to/your-key.pem \
-out /path/to/your-cert.pem \
-subj "/CN=localhost" \
-days 3650
$SU chown \
caddy:caddy \
/path/to/your-key.pem \
/path/to/your-cert.pem
[...]
(tls) {
- tls internal {
+ tls /path/to/your-cert.pem /path/to/your-key.pem {
on_demand
}
}
[...]
Create the Caddy service
$SU $EDITOR /etc/init.d/caddy
#!/sbin/openrc-run
: ${CADDY_CONFIGFILE:=/etc/caddy/Caddyfile}
: ${CADDY_DATADIR:=/var/lib/caddy}
: ${CADDY_LOGDIR:=/var/log/caddy}
: ${CADDY_USER:=caddy}
: ${CADDY_GROUP:=caddy}
: ${CADDY_BIN:=/usr/bin/caddy}
: ${CADDY_OPTS=${CADDY_OPTS}}
: ${CADDY_SIGTERM_TIMEOUT:=600}
CADDY_PIDDIR="/run/caddy"
name="Caddy web server"
description="Fast, multi-platform web server with automatic HTTPS"
required_files="${CADDY_CONFIGFILE}"
pidfile="${CADDY_PIDDIR}/${SVCNAME}.pid"
retry="${CADDY_SIGTERM_TIMEOUT}"
capabilities="^cap_net_bind_service"
command="${CADDY_BIN}"
command_args="run
--config ${CADDY_CONFIGFILE}
${CADDY_OPTS}"
command_user="${CADDY_USER}:${CADDY_GROUP}"
command_background="true"
start_stop_daemon_args="--env XDG_CONFIG_HOME=${CADDY_DATADIR%/caddy}
--env XDG_DATA_HOME=${CADDY_DATADIR%/caddy}
--stdout ${CADDY_LOGDIR}/debug.log
--stderr ${CADDY_LOGDIR}/debug.log"
extra_commands="checkconfig"
description_checkconfig="Check configuration"
extra_started_commands="reload"
description_reload="Reload configuration without downtime"
depend() {
need net localmount
after firewall
}
start_pre() {
checkpath --file --mode 0660 --owner "${command_user}" "${CADDY_CONFIGFILE}"
checkpath --directory --mode 0750 --owner "${command_user}" "${CADDY_DATADIR}"
checkpath --directory --mode 0755 --owner "${command_user}" "${CADDY_LOGDIR}"
checkpath --directory --mode 0755 --owner "${command_user}" "${CADDY_PIDDIR}"
checkconfig
}
checkconfig() {
if [ ! -f "${CADDY_CONFIGFILE}" ] ; then
ewarn "${CADDY_CONFIGFILE} does not exist." && return 1
fi
$command validate ${command_args#run} > /dev/null 2>&1
eend $?
}
reload() {
if ! service_started "${SVCNAME}" ; then
eerror "${SVCNAME} isn't running" && return 1
fi
checkconfig || { eerror "Invalid configuration file !" && return 1; }
ebegin "Reloading ${SVCNAME}"
$command reload --force ${command_args#run} > /dev/null 2>&1
eend $?
}
- Enable execution permission
$SU chmod +x /etc/init.d/caddy
Enable and start the Caddy service
$SU rc-service caddy start
$SU rc-update add caddy
- You can monitor the Caddy logs by entering this command. Exit with
Ctrl + C
tail -f /var/log/caddy/debug.log