Files
nixfiles/hosts/PiZero2W/serial-ppp.nix
T

90 lines
3.0 KiB
Nix
Raw Normal View History

# The serial half of the Psion sidecar: a PPP link to a Psion 5MX over
# /dev/ttyAMA0 (RS232 level shifter on the GPIO header, 115200 8N1 with
# RTS/CTS), masqueraded out of wifi, plus a telnet login for the Psion's
# terminal client.
#
# Cleartext telnet and unauthenticated PPP are safe *only* because the link is
# a two-node cable: the peer is a machine from 1999 that speaks no TLS. Nothing
# here is exposed to wlan0.
{ pkgs, ... }:
let
# Point-to-point addresses for the serial link; nothing else routes here.
piAddress = "10.0.0.1";
psionAddress = "10.0.0.2";
in
{
# pppd needs exclusive use of the port. NixOS starts a getty on any serial
# console named in boot.kernelParams; ttyAMA0 is not one today, but disable it
# explicitly so a later kernel-param change cannot silently steal the line.
systemd.services."serial-getty@ttyAMA0".enable = false;
services.pppd = {
enable = true;
peers.psion.config = ''
/dev/ttyAMA0
115200
${piAddress}:${psionAddress}
# Hardware flow control, matching the Psion's modem profile.
crtscts
# A null-modem cable has no carrier detect and no peer to authenticate.
local
noauth
# The systemd unit is Type=notify, so pppd must stay in the foreground.
nodetach
lock
# Wait for the Psion rather than failing when it is unplugged, and keep
# waiting for the next time it is plugged back in.
passive
persist
maxfail 0
holdoff 1
# Hand the Psion resolvers over the link, so its Internet profile can set
# "get DNS from server = True" instead of hard-coding them.
ms-dns 1.1.1.1
ms-dns 8.8.8.8
'';
};
# The Psion's route to the internet. The original write-up used pppd's
# proxyarp instead; NAT keeps the Psion out of the LAN broadcast domain and
# does not depend on what the wifi router tolerates.
networking.nat = {
enable = true;
externalInterface = "wlan0";
internalIPs = [ "${psionAddress}/32" ];
};
# Everything the Psion connects to (telnet here, POP3/SMTP in
# ./email-proxy.nix) is reachable over the PPP link and nowhere else.
networking.firewall.trustedInterfaces = [ "ppp0" ];
# The Psion's terminal client speaks telnet over TCP, which it renders far
# better than the raw serial console. Socket-activated, one process per
# connection; busybox's telnetd in inetd mode hands straight over to login.
systemd.sockets.telnetd = {
description = "Telnet login socket for the Psion";
wantedBy = [ "sockets.target" ];
listenStreams = [ "${piAddress}:23" ];
socketConfig = {
Accept = true;
# ppp0 (and with it 10.0.0.1) only exists while the Psion is connected;
# FreeBind lets the socket be listening before that.
FreeBind = true;
};
};
systemd.services."telnetd@" = {
description = "Telnet login for the Psion";
serviceConfig = {
ExecStart = "-${pkgs.busybox}/bin/busybox telnetd -i -l ${pkgs.shadow}/bin/login";
StandardInput = "socket";
StandardError = "journal";
};
};
}