Compare commits

...

17 Commits
main ... lte

Author SHA1 Message Date
Daniel Barlow dc3ade7969 commentary 2024-05-14 22:27:37 +01:00
Daniel Barlow 7ece8dde5e add hacky wwan service with hardcoding all over 2024-05-14 22:19:34 +01:00
Daniel Barlow 5a19af318e ref cdc-ncm module by corretc name 9suash) 2024-05-14 21:57:28 +01:00
Daniel Barlow 6d36f0eb13 remove leftovers from arhcive example 2024-05-14 18:08:53 +01:00
Daniel Barlow 5d246e1f1a create cdc-ncm module 2024-05-14 18:07:33 +01:00
Daniel Barlow 0e2e44c6ee barebones usb_modeswitch package 2024-05-14 12:56:58 +01:00
Daniel Barlow e2c5615677 l2tp set default route via tunnel 2024-05-14 12:52:50 +01:00
Daniel Barlow ab59c852e2 exec xl2tpd
haven't fully worked out why, but without this s6 is unable to stop it.
2024-05-13 18:41:06 +01:00
Daniel Barlow 98d198960b think 2024-05-13 18:41:06 +01:00
Daniel Barlow d98f011292 add rudimentary l2tp service module 2024-05-13 18:41:06 +01:00
Daniel Barlow 991de7eb9e bordervm enable nat 2024-05-13 18:41:06 +01:00
Daniel Barlow 513c69cb5b gl-ar750 appendDTB 2024-05-13 18:41:06 +01:00
Daniel Barlow 15856d224c memorable net device names for gl-ar750
linux's view of eth1 and eth0 are opposite to that of u-boot
2024-05-13 18:41:06 +01:00
Daniel Barlow abbdda7b30 run dhcp server on bordervm
this is for testing clients that have dhcp upstream
2024-05-13 18:41:06 +01:00
Daniel Barlow e56b761ba3 rename overlaid dnsmasq package -> dnsmasqSmall
avoid clobbering the regular one
2024-05-13 18:41:06 +01:00
Daniel Barlow 15ec172739 tftp addresses 2024-05-13 18:41:06 +01:00
Daniel Barlow 6ddba0f68b think 2024-05-13 18:41:06 +01:00
12 changed files with 405 additions and 13 deletions

View File

@ -4726,9 +4726,9 @@ outside of it
[X] 2) if so, convert it to lualinux [X] 2) if so, convert it to lualinux
[X] 3) add netlink socket to event loop [X] 3) add netlink socket to event loop
[X] 4) make it send messages to subscribers [X] 4) make it send messages to subscribers
5) package it [X] 5) package it
6) make uevent-watcher use it instead of netlink directly [X] 6) make uevent-watcher use it instead of netlink directly
7) write an inout test variant that has the stick inserted [X] 7) write an inout test variant that has the stick inserted
at boot time already at boot time already
I'm also thinking we could wrap the raw fds from lualinux into small I'm also thinking we could wrap the raw fds from lualinux into small
@ -4741,3 +4741,113 @@ state before subscribing them [ needs a test ]
figure out what event format the subscribers want? lua-ish or send the figure out what event format the subscribers want? lua-ish or send the
same messages as udev would? If we're going to send the originals, same messages as udev would? If we're going to send the originals,
should we store them alongside the parsed, or reconstruct from parsed? should we store them alongside the parsed, or reconstruct from parsed?
Sat Apr 27 21:52:11 BST 2024
We have a passing inout test. Next thing to do is try it on
the actual arhcive hardware
Next big thing is some kind of failovery service. Almost-obvious
candidate is LTE failover with aaisp l2tp tunnel
Tue Apr 30 23:27:30 BST 2024
I want to connect my new ip camera to arthur without letting it reach the
internet, or the internet reach it.
we could plug it into a gl.inet box running dhcp server on lan
and client on wan, then use NAT to expose the camera's http and rtsp
ports on whatever address it has on the wan interface
Tue May 7 22:23:49 BST 2024
If we want to build a config with an l2tp upstream, it needs an
underlying dhcp interface not pppoe as we can't use the bordervm l2tp
account simultaneously. Having bordervm do dhcp might be quite useful
anyway for other applications, although it will have to double-nat to
the internet. We could give it an aaisp /64 and have routable ipv6 but
maybe that's a level of faff too high.
Given that we can build xl2tpd and a service for it.
're using the same l2tp account for thingy that we use to simulate ppp,
we need an upstream which is not ppp
We need a less shit coldplug that copes with filenames containing spaces (!)
Fri May 10 00:33:14 BST 2024
Getting xl2tp hackily running turned out to be not a lot of work. However,
we need to figure out routing
- we need a route on lan device to the dns to lookup l2tp.aaisp.net.uk
- we need a route on lan device to l2tp.aaisp.net.uk
also it doesn't die when the tunnel closes, which is a bit shit
maybe this is where we lean into health check services
a health check service is just a service that watches another service
and kills it if it's not healthy.
for xl2tpd, "not healthy" is "there is no ppp process" or "there is no
tunnel" or "the tunnel has no sessions". I don't know how we
(robustly) test for no ppp process associated with the l2tp peer
when ppp quits, does the tunnel come down?
in xl2tld.c child_handler we respond to sigchld by closing c->fd
and setting it to -1
Sat May 11 17:55:04 BST 2024
A better way to monitor the connection health would be to ping a
computer on the internet (preferably one that doesn't mind being
pinged). If we combine autodial with "is $isp still there" then we
should have something fairly robust.
xl2tpd spawns pppd, we should equip it with config that writes the
ppp outputs (ip address etc) to the xl2tp service directory so
that it can be used like a regular ppp. This will also make
it possible to have the health check work by pinging the peer address
Sun May 12 22:33:09 BST 2024
sleep until the interface is probably up
failure counter = 0
loop indefinitely
get outputs/peer-address of watched ppp service
ping it
if ok
reset failure counter
else
increment failure counter
fi
if failure counter > threshold
bounce the ppp service
exit, if previous action didn't do that already
end
sleep(check interval)
end loop
# ps ax | grep l2tp
72 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp
73 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp-log
122 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
1099 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
1102 root 1104 S {xl2tpd} /nix/store/i1bbqh7vybam03l6jzf4sm4np3k4ack5
1115 root 1420 S grep l2tp
# s6-rc -d change l2tp.aaisp.net.uk.l2tp
# ps ax | grep l2tp
72 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp
73 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp-log
122 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
1102 root 1104 S {xl2tpd} /nix/store/i1bbqh7vybam03l6jzf4sm4np3k4ack5
1122 root 1420 S grep l2tp
we are the LAC, aaisp are the LNS

View File

@ -80,8 +80,19 @@ in {
}; };
}; };
services.openssh.enable = true; services.openssh.enable = true;
services.dnsmasq = {
enable = true;
resolveLocalQueries = false;
settings = {
# domain-needed = true;
dhcp-range = [ "10.0.0.10,10.0.0.240" ];
interface = "eth1";
};
};
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ]; systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
virtualisation = { virtualisation = {
qemu = { qemu = {
networkingOptions = []; networkingOptions = [];
@ -122,6 +133,11 @@ in {
useDHCP = false; useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}]; ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
}; };
nat = {
enable = true;
internalInterfaces = [ "eth1" ];
externalInterface ="eth0";
};
}; };
users.users.liminix = { users.users.liminix = {
isNormalUser = true; isNormalUser = true;

View File

@ -125,8 +125,14 @@
networkInterfaces = networkInterfaces =
let inherit (config.system.service.network) link; let inherit (config.system.service.network) link;
in { in {
lan = link.build { ifname = "eth0"; }; lan = link.build {
wan = link.build { ifname = "eth1"; }; ifname = "lan";
devpath = "/devices/platform/ahb/19000000.eth";
};
wan = link.build {
ifname = "wan";
devpath = "/devices/platform/ahb/1a000000.eth";
};
wlan = link.build { wlan = link.build {
ifname = "wlan0"; ifname = "wlan0";
dependencies = [ mac80211 ]; dependencies = [ mac80211 ];
@ -149,6 +155,7 @@
}; };
boot.tftp = { boot.tftp = {
loadAddress = lim.parseInt "0x00A00000"; loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
}; };
kernel = { kernel = {
src = pkgs.pkgsBuildBuild.fetchurl { src = pkgs.pkgsBuildBuild.fetchurl {

View File

@ -18,8 +18,8 @@
in rec { in rec {
boot = { boot = {
tftp = { tftp = {
serverip = "192.168.8.148"; serverip = "10.0.0.1";
ipaddr = "192.168.8.251"; ipaddr = "10.0.0.8";
}; };
}; };
@ -124,9 +124,7 @@ in rec {
users.root = { users.root = {
passwd = lib.mkForce secrets.root.passwd; passwd = lib.mkForce secrets.root.passwd;
# openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = secrets.root.keys;
# (builtins.readFile "/home/dan/.ssh/id_rsa.pub")
# ];
}; };
users.backup = { users.backup = {

86
examples/l2tp.nix Normal file
View File

@ -0,0 +1,86 @@
{
config,
pkgs,
lib,
...
}: let
secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix;
lns = "l2tp.aaisp.net.uk";
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText dropbear ifwait serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
};
imports = [
../modules/cdc-ncm
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
../modules/ppp
];
hostname = "thing";
services.dhcpc = svc.network.dhcp.client.build {
interface = config.services.wwan;
dependencies = [ config.services.hostname ];
};
services.sshd = svc.ssh.build { };
services.resolvconf = oneshot rec {
dependencies = [ services.dhcpc ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in $(output ${services.dhcpc} dns); do
echo "nameserver $i" > resolv.conf
done
)
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
srv = dir {};
};
services.lnsroute = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = lns;
dependencies = [services.dhcpc];
};
services.l2tp = svc.l2tp.build {
inherit lns;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" rsecrets.l2tp.name
"password" rsecrets.l2tp.password
];
dependencies = [ services.lnsroute ];
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.l2tp} router)";
target = "default";
dependencies = [services.l2tp];
};
users.root = {
passwd = lib.mkForce secrets.root.passwd;
openssh.authorizedKeys.keys = secrets.root.keys;
};
}

View File

@ -0,0 +1,56 @@
{ config, pkgs, lib, ... }:
let
inherit (pkgs.liminix.services) oneshot;
svc = config.system.service;
in {
config = {
kernel.config = {
USB_NET_HUAWEI_CDC_NCM = "y";
USB_USBNET = "y";
USB_SERIAL = "y";
USB_SERIAL_OPTION = "y";
};
# https://www.0xf8.org/2017/01/flashing-a-huawei-e3372h-4g-lte-stick-from-hilink-to-stick-mode/
services.wwan = let
chat = lib.escapeShellArgs [
# Your usb modem thing might present as a tty that you run PPP
# over, or as a network device ("ndis" or "ncm"). The latter
# kind is to be preferred, at least in principle, because it's
# faster. This initialization sequence works for the Huawei
# E3372, and took much swearing: the error messages are *awful*
"" "AT"
"OK" "ATZ"
# create PDP context
"OK" "AT+CGDCONT=1,\"IP\",\"data.uk\""
# activate PDP context
"OK" "AT+CGACT=1,1"
# setup username and password per requirements of sim provider.
# (caret is special to chat, so needs escaping in AT commands)
"OK" "AT\\^AUTHDATA=1,2,\"1p\",\"one2one\",\"user\""
# start the thing (I am choosing to read this as "NDIS DialUP")
"OK" "AT\\^NDISDUP=1,1"
];
modemConfig = oneshot {
name = "modem-configure";
# this is currently only going to work if there is one
# modem only plugged in, it is plugged in already at boot,
# and nothing else is providing a USB tty.
# https://stackoverflow.com/questions/5477882/how-to-i-detect-whether-a-tty-belonging-to-a-gsm-3g-modem-is-a-data-or-control-p
up = ''
sleep 2
${pkgs.usb-modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode
sleep 5
${pkgs.ppp}/bin/chat -s -v ${chat} 0<>/dev/ttyUSB0 1>&0
'';
down = "chat -v '' ATZ OK </dev/ttyUSB0 >&0";
};
in svc.network.link.build {
ifname = "wwan0";
dependencies = [ modemConfig ];
};
};
}

View File

@ -1,6 +1,6 @@
{ {
liminix liminix
, dnsmasq , dnsmasqSmall
, serviceFns , serviceFns
, lib , lib
}: }:
@ -27,7 +27,7 @@ longrun {
dependencies = [ interface ]; dependencies = [ interface ];
run = '' run = ''
. ${serviceFns} . ${serviceFns}
${dnsmasq}/bin/dnsmasq \ ${dnsmasqSmall}/bin/dnsmasq \
--user=${user} \ --user=${user} \
--domain=${domain} \ --domain=${domain} \
--group=${group} \ --group=${group} \

View File

@ -17,6 +17,9 @@ in {
system.service.pppoe = mkOption { system.service.pppoe = mkOption {
type = liminix.lib.types.serviceDefn; type = liminix.lib.types.serviceDefn;
}; };
system.service.l2tp = mkOption {
type = liminix.lib.types.serviceDefn;
};
}; };
config = { config = {
system.service.pppoe = pkgs.liminix.callService ./pppoe.nix { system.service.pppoe = pkgs.liminix.callService ./pppoe.nix {
@ -29,6 +32,16 @@ in {
description = "options supplied on ppp command line"; description = "options supplied on ppp command line";
}; };
}; };
system.service.l2tp = pkgs.liminix.callService ./l2tp.nix {
lns = mkOption {
type = types.str;
description = "hostname or address of the L2TP network server";
};
ppp-options = mkOption {
type = types.listOf types.str;
description = "options supplied on ppp command line";
};
};
kernel = { kernel = {
config = { config = {
PPP = "y"; PPP = "y";
@ -36,6 +49,8 @@ in {
PPP_DEFLATE = "y"; PPP_DEFLATE = "y";
PPP_ASYNC = "y"; PPP_ASYNC = "y";
PPP_SYNC_TTY = "y"; PPP_SYNC_TTY = "y";
PPPOL2TP = "y";
L2TP = "y";
}; };
}; };
}; };

62
modules/ppp/l2tp.nix Normal file
View File

@ -0,0 +1,62 @@
{
liminix
, lib
, ppp
, pppoe
, writeAshScript
, writeText
, serviceFns
, xl2tpd
} :
{ lns, ppp-options }:
let
inherit (liminix.services) longrun;
name = "${lns}.l2tp";
ip-up = writeAshScript "ip-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $1 > ifname
echo $2 > tty
echo $3 > speed
echo $4 > address
echo $5 > peer-address
echo $DNS1 > ns1
echo $DNS2 > ns2
)
echo >/proc/self/fd/10
'';
ip6-up = writeAshScript "ip6-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $4 > ipv6-address
echo $5 > ipv6-peer-address
)
echo >/proc/self/fd/10
'';
ppp-options' = ppp-options ++ [
"ip-up-script" ip-up
"ipv6-up-script" ip6-up
"ipparam" name
"nodetach"
"usepeerdns"
"logfd" "2"
];
conf = writeText "xl2tpd.conf" ''
[lac upstream]
lns = ${lns}
require authentication = no
pppoptfile = ${writeText "ppp-options" ppp-options'}
autodial = yes
redial = yes
'';
control = "/run/xl2tpd/control-${name}";
in
longrun {
inherit name;
run = ''
mkdir -p /run/xl2tpd
touch ${control}
exec ${xl2tpd}/bin/xl2tpd -D -p /run/xl2tpd/${name}.pid -c ${conf} -C ${control}
'';
notification-fd = 10;
}

View File

@ -94,7 +94,7 @@ extraPkgs // {
else {} else {}
); );
dnsmasq = dnsmasqSmall =
let d = prev.dnsmasq.overrideAttrs(o: { let d = prev.dnsmasq.overrideAttrs(o: {
preBuild = '' preBuild = ''
makeFlagsArray=("COPTS=") makeFlagsArray=("COPTS=")
@ -271,6 +271,8 @@ extraPkgs // {
''; '';
}; };
libusb1 = prev.libusb1.override { enableUdev = false; };
util-linux-small = prev.util-linux.override { util-linux-small = prev.util-linux.override {
ncursesSupport = false; ncursesSupport = false;
pamSupport = false; pamSupport = false;

View File

@ -110,6 +110,7 @@ in {
systemconfig = callPackage ./systemconfig {}; systemconfig = callPackage ./systemconfig {};
tufted = callPackage ./tufted {}; tufted = callPackage ./tufted {};
uevent-watch = callPackage ./uevent-watch {}; uevent-watch = callPackage ./uevent-watch {};
usb-modeswitch = callPackage ./usb-modeswitch {};
writeAshScript = callPackage ./write-ash-script {}; writeAshScript = callPackage ./write-ash-script {};
writeFennel = callPackage ./write-fennel {}; writeFennel = callPackage ./write-fennel {};
writeFennelScript = callPackage ./write-fennel-script {}; writeFennelScript = callPackage ./write-fennel-script {};

View File

@ -0,0 +1,39 @@
# usb modeswitch without udev, tcl, coreutils, bash dependencies
{ stdenv
, lib
, fetchurl
, pkg-config
, libusb1
}:
let
pname = "usb-modeswitch";
version = "2.6.0";
in stdenv.mkDerivation {
inherit pname version;
src = fetchurl {
url = "http://www.draisberghof.de/usb_modeswitch/${pname}-${version}.tar.bz2";
sha256 = "18wbbxc5cfsmikba0msdvd5qlaga27b32nhrzicyd9mdddp265f2";
};
preBuild = ''
makeFlagsArray+=(LIBS="$($PKG_CONFIG --libs --cflags libusb-1.0)")
'';
makeFlags = [
"PREFIX=$(out)"
"usb_modeswitch"
];
buildInputs = [ libusb1 ];
nativeBuildInputs = [ pkg-config ];
installPhase = ''
mkdir -p $out/bin
cp usb_modeswitch $out/bin
'';
meta = {
license = lib.licenses.gpl2;
maintainers = [];
};
}