modules/proxy: multi-user support
This commit is contained in:
parent
7727c5cf43
commit
082e64b960
3 changed files with 159 additions and 137 deletions
|
@ -3,6 +3,7 @@
|
||||||
config = {
|
config = {
|
||||||
sops = {
|
sops = {
|
||||||
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
||||||
|
defaultSopsFile = ./secrets/secrets.yaml;
|
||||||
secrets = {
|
secrets = {
|
||||||
wg_private_key = {
|
wg_private_key = {
|
||||||
owner = "root";
|
owner = "root";
|
||||||
|
@ -12,14 +13,6 @@
|
||||||
owner = "root";
|
owner = "root";
|
||||||
sopsFile = ./secrets + "/${config.networking.hostName}.yaml";
|
sopsFile = ./secrets + "/${config.networking.hostName}.yaml";
|
||||||
};
|
};
|
||||||
"sing-box/password" = {
|
|
||||||
owner = "root";
|
|
||||||
sopsFile = ./secrets/secrets.yaml;
|
|
||||||
};
|
|
||||||
"sing-box/uuid" = {
|
|
||||||
owner = "root";
|
|
||||||
sopsFile = ./secrets/secrets.yaml;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
swapDevices = [
|
swapDevices = [
|
||||||
|
@ -32,6 +25,7 @@
|
||||||
custom.prometheus.exporters = {
|
custom.prometheus.exporters = {
|
||||||
enable = true;
|
enable = true;
|
||||||
node.enable = true;
|
node.enable = true;
|
||||||
|
blackbox.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
custom.monitoring = {
|
custom.monitoring = {
|
||||||
|
@ -44,6 +38,11 @@
|
||||||
auth.enable = true;
|
auth.enable = true;
|
||||||
proxyServer = {
|
proxyServer = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
users = [
|
||||||
|
"wyj"
|
||||||
|
"yhb"
|
||||||
|
"xin"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
sing-box:
|
sing-box:
|
||||||
password: ENC[AES256_GCM,data:qCc1v8nAL0oYisRinMDXGrBQA+r6XNoa,iv:eTxtad4kEdE28XqnrZEek8BtXNY1rNgLvGLxlMzRtl4=,tag:s/shWAkYE4DSnScpTY8ulQ==,type:str]
|
users:
|
||||||
uuid: ENC[AES256_GCM,data:lEpz15sLOVrGDzQwTJyS+tFJY0bMeO265bxocWAjB6qrvxYx,iv:lhk5jl/udUH3AZEuk5ffuvin/qhRUaOZ/3nk1Jaw+DI=,tag:4mKFIVKT+D47njfDsxe9iA==,type:str]
|
wyj:
|
||||||
|
password: ENC[AES256_GCM,data:yp+T3eci9RiuZzdmRSq5nTjHaz8e/Rri,iv:hIPc+7YHUnaIdU9O8GGx3r7l3oBA6prQb+KBQV0G+8k=,tag:2GNiBP4PQy+KGHgLupKGSg==,type:str]
|
||||||
|
uuid: ENC[AES256_GCM,data:Qrgil6G7pjQAQzCCOlstDi27EqqmSuBMhs+RTl9++wrPrIgJ,iv:u+3Z17uX4I6li2qd9UP3y+WaKn7aKfbb3J6H1Pyc1QY=,tag:hSa4AB383/B58XMmZ8LIfQ==,type:str]
|
||||||
|
yhb:
|
||||||
|
password: ENC[AES256_GCM,data:TwRct68TePpcZcnpWIQpFaF23WGMre8=,iv:YU4mQNm0rt2u4ItJwQ8nZPEmJi0+lmEIPG2Kxh/nI58=,tag:ukZem38O/b42dEKM3CYa+w==,type:str]
|
||||||
|
uuid: ENC[AES256_GCM,data:6hVhEqWPLVrn8rCS4x/eapd+iL7JRaXtOGCj9uuPlkGjBTMK,iv:VZ27KWCY6/K5GoNwRNmaRWzqfV7+8iFjtias1vKeGfA=,tag:8mhmZPooxHaGNYdznuFhMQ==,type:str]
|
||||||
|
xin:
|
||||||
|
password: ENC[AES256_GCM,data:SRiPFO+Uwy/PT41SIg7eI68wk4AX6so=,iv:aXwP5wa1IrlnvFo/ZL+DYFFHDdWw2Z83de3ApHUTsXo=,tag:sxXoy1FnDxZBQCDeNxphzQ==,type:str]
|
||||||
|
uuid: ENC[AES256_GCM,data:7xK53SO4x0tOIEIYl6kmmAvnpdsR/tYQoG1t/ytsnO4QqWY3,iv:i694Fnu7g1OA3IGzSaoSGA5/eMPo+I/1TZbYuaQrgNA=,tag:4cUlioJn/IvsvZclgboOSA==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
|
@ -43,8 +51,8 @@ sops:
|
||||||
K1F1SzI2NFNIKzlreVBXSjAxaUxQd28KFaf1uu7OlqIe0TirJFgS3iPjhXPyfNDE
|
K1F1SzI2NFNIKzlreVBXSjAxaUxQd28KFaf1uu7OlqIe0TirJFgS3iPjhXPyfNDE
|
||||||
m2XUjzdXp+chJCzVOFvpYStqz+e08ADEc+jp3YsTLcxyqvXhQdyL/Q==
|
m2XUjzdXp+chJCzVOFvpYStqz+e08ADEc+jp3YsTLcxyqvXhQdyL/Q==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2024-12-02T05:26:17Z"
|
lastmodified: "2024-12-06T04:35:52Z"
|
||||||
mac: ENC[AES256_GCM,data:K94zFWPWGUisLCqDjSLs17QxHXPH4tPU/98Sb4lCnt7IRAIn14x/T+BnInY/DK+DOVLLtzSfuN0kgzzGjSzwJx5Vq1G3MkhngRQQRT9dvODTCMAw6lPt98Ofw1CEEsFQnpYo9zIUlCGKg2YPKFLqE7OjkPxqw7VYvgzr5dDw58s=,iv:3xcJfNX5v/e9HgZt3UrHs2/C5ivaBV1rXKIBs9hKKFg=,tag:RQPQQ1cmZiOpQjUwqnzZQA==,type:str]
|
mac: ENC[AES256_GCM,data:DAg4UTwNv+rs6hye2z5UUtA1a4yZbFaAWjLoKAXf87tKgBCZzK8C1q6gLyTQOqp07ptYQd5Q951kfE1a/35SFJsubREzJmu6haxznRgq7pO5HDGqgtjYEHsngsWZh3bUSX/aG2dLISdD81VY68nLzTO0r4h/SL6DNG36RzJgL8E=,iv:V0WhENNt/Szi5VWVD2t5AsWP1tOZUGjFjMNYPDq59XI=,tag:ThRstdzVNtSs6E7qlvKPOw==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.9.1
|
version: 3.9.1
|
||||||
|
|
|
@ -21,106 +21,100 @@ let
|
||||||
config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
|
config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
|
||||||
};
|
};
|
||||||
|
|
||||||
mkSingConfig =
|
mkSingConfig = users: {
|
||||||
{ uuid, password, ... }:
|
log = {
|
||||||
{
|
level = "warn";
|
||||||
log = {
|
};
|
||||||
level = "warn";
|
inbounds =
|
||||||
};
|
[
|
||||||
inbounds =
|
{
|
||||||
[
|
tag = "sg0";
|
||||||
{
|
type = "trojan";
|
||||||
tag = "sg0";
|
|
||||||
type = "trojan";
|
|
||||||
listen = "::";
|
|
||||||
listen_port = cfg.trojan.port;
|
|
||||||
tcp_multi_path = true;
|
|
||||||
tcp_fast_open = true;
|
|
||||||
users = [
|
|
||||||
{
|
|
||||||
name = "proxy";
|
|
||||||
password = {
|
|
||||||
_secret = password;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
tls = singTls;
|
|
||||||
}
|
|
||||||
]
|
|
||||||
++ lib.forEach (lib.range 6311 6314) (port: {
|
|
||||||
tag = "sg" + toString (port - 6310);
|
|
||||||
type = "tuic";
|
|
||||||
listen = "::";
|
listen = "::";
|
||||||
listen_port = port;
|
listen_port = cfg.trojan.port;
|
||||||
congestion_control = "bbr";
|
tcp_multi_path = true;
|
||||||
users = [
|
tcp_fast_open = true;
|
||||||
|
users = map (user: {
|
||||||
|
name = user.name;
|
||||||
|
password = {
|
||||||
|
_secret = user.passwordFile;
|
||||||
|
};
|
||||||
|
}) users;
|
||||||
|
tls = singTls;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
++ lib.forEach (lib.range 6311 6314) (port: {
|
||||||
|
tag = "sg" + toString (port - 6310);
|
||||||
|
type = "tuic";
|
||||||
|
listen = "::";
|
||||||
|
listen_port = port;
|
||||||
|
congestion_control = "bbr";
|
||||||
|
users = map (user: {
|
||||||
|
name = user.name;
|
||||||
|
uuid = {
|
||||||
|
_secret = user.uuidFile;
|
||||||
|
};
|
||||||
|
password = {
|
||||||
|
_secret = user.passwordFile;
|
||||||
|
};
|
||||||
|
}) users;
|
||||||
|
tls = singTls;
|
||||||
|
});
|
||||||
|
outbounds =
|
||||||
|
# warp outbound goes first to make it default outbound
|
||||||
|
(lib.optionals (cfg.warp.onTuic or cfg.warp.onTrojan) [
|
||||||
|
{
|
||||||
|
type = "wireguard";
|
||||||
|
tag = "wg-out";
|
||||||
|
private_key = {
|
||||||
|
_secret = config.sops.secrets.wg_private_key.path;
|
||||||
|
};
|
||||||
|
local_address = [
|
||||||
|
"172.16.0.2/32"
|
||||||
|
{ _secret = config.sops.secrets.wg_ipv6_local_addr.path; }
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
{
|
{
|
||||||
name = "proxy";
|
public_key = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
|
||||||
uuid = {
|
allowed_ips = [
|
||||||
_secret = uuid;
|
"0.0.0.0/0"
|
||||||
};
|
"::/0"
|
||||||
password = {
|
];
|
||||||
_secret = password;
|
server = "162.159.192.1";
|
||||||
};
|
server_port = 500;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
tls = singTls;
|
}
|
||||||
});
|
])
|
||||||
outbounds =
|
++ [
|
||||||
# warp outbound goes first to make it default outbound
|
|
||||||
(lib.optionals (cfg.warp.onTuic or cfg.warp.onTrojan) [
|
|
||||||
{
|
|
||||||
type = "wireguard";
|
|
||||||
tag = "wg-out";
|
|
||||||
private_key = {
|
|
||||||
_secret = config.sops.secrets.wg_private_key.path;
|
|
||||||
};
|
|
||||||
local_address = [
|
|
||||||
"172.16.0.2/32"
|
|
||||||
{ _secret = config.sops.secrets.wg_ipv6_local_addr.path; }
|
|
||||||
];
|
|
||||||
peers = [
|
|
||||||
{
|
|
||||||
public_key = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
|
|
||||||
allowed_ips = [
|
|
||||||
"0.0.0.0/0"
|
|
||||||
"::/0"
|
|
||||||
];
|
|
||||||
server = "162.159.192.1";
|
|
||||||
server_port = 500;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
])
|
|
||||||
++ [
|
|
||||||
|
|
||||||
|
{
|
||||||
|
type = "direct";
|
||||||
|
tag = "direct";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
route = {
|
||||||
|
rules =
|
||||||
|
[
|
||||||
{
|
{
|
||||||
type = "direct";
|
inbound = "sg4";
|
||||||
tag = "direct";
|
outbound = "direct";
|
||||||
}
|
}
|
||||||
];
|
]
|
||||||
route = {
|
++ (lib.optionals (!cfg.warp.onTuic) (
|
||||||
rules =
|
lib.forEach (lib.range 1 3) (i: {
|
||||||
[
|
inbound = "sg${toString i}";
|
||||||
{
|
outbound = "direct";
|
||||||
inbound = "sg4";
|
})
|
||||||
outbound = "direct";
|
))
|
||||||
}
|
++ (lib.optionals (!cfg.warp.onTrojan) [
|
||||||
]
|
{
|
||||||
++ (lib.optionals (!cfg.warp.onTuic) (
|
inbound = "sg0";
|
||||||
lib.forEach (lib.range 1 3) (i: {
|
outbound = "direct";
|
||||||
inbound = "sg${toString i}";
|
}
|
||||||
outbound = "direct";
|
]);
|
||||||
})
|
|
||||||
))
|
|
||||||
++ (lib.optionals (!cfg.warp.onTrojan) [
|
|
||||||
{
|
|
||||||
inbound = "sg0";
|
|
||||||
outbound = "direct";
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.commonSettings.proxyServer = {
|
options.commonSettings.proxyServer = {
|
||||||
|
@ -137,40 +131,61 @@ in
|
||||||
onTrojan = mkEnableOption "forward to warp in trojan";
|
onTrojan = mkEnableOption "forward to warp in trojan";
|
||||||
onTuic = mkEnableOption "forward to warp in first two port of tuic";
|
onTuic = mkEnableOption "forward to warp in first two port of tuic";
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
users = mkOption {
|
||||||
boot.kernel.sysctl = {
|
type = lib.types.listOf lib.types.str;
|
||||||
"net.core.default_qdisc" = "fq";
|
|
||||||
"net.ipv4.tcp_congestion_control" = "bbr";
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.trustedInterfaces = [ "tun0" ];
|
|
||||||
|
|
||||||
security.acme = {
|
|
||||||
acceptTerms = true;
|
|
||||||
certs.${config.deployment.targetHost} = {
|
|
||||||
email = "me@namely.icu";
|
|
||||||
# Avoid port conflict
|
|
||||||
listenHTTP = if config.services.caddy.enable then ":30310" else ":80";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."http://${config.deployment.targetHost}:80".extraConfig = ''
|
|
||||||
reverse_proxy 127.0.0.1:30310
|
|
||||||
'';
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [
|
|
||||||
80
|
|
||||||
cfg.trojan.port
|
|
||||||
];
|
|
||||||
networking.firewall.allowedUDPPorts = [ ] ++ (lib.range 6311 6314);
|
|
||||||
|
|
||||||
services.sing-box = {
|
|
||||||
enable = true;
|
|
||||||
settings = mkSingConfig {
|
|
||||||
uuid = config.sops.secrets."sing-box/uuid".path;
|
|
||||||
password = config.sops.secrets."sing-box/password".path;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (
|
||||||
|
{
|
||||||
|
boot.kernel.sysctl = {
|
||||||
|
"net.core.default_qdisc" = "fq";
|
||||||
|
"net.ipv4.tcp_congestion_control" = "bbr";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.trustedInterfaces = [ "tun0" ];
|
||||||
|
|
||||||
|
security.acme = {
|
||||||
|
acceptTerms = true;
|
||||||
|
certs.${config.deployment.targetHost} = {
|
||||||
|
email = "me@namely.icu";
|
||||||
|
# Avoid port conflict
|
||||||
|
listenHTTP = if config.services.caddy.enable then ":30310" else ":80";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.caddy.virtualHosts."http://${config.deployment.targetHost}:80".extraConfig = ''
|
||||||
|
reverse_proxy 127.0.0.1:30310
|
||||||
|
'';
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
80
|
||||||
|
cfg.trojan.port
|
||||||
|
];
|
||||||
|
networking.firewall.allowedUDPPorts = [ ] ++ (lib.range 6311 6314);
|
||||||
|
|
||||||
|
services.sing-box = {
|
||||||
|
enable = true;
|
||||||
|
settings = (
|
||||||
|
mkSingConfig (
|
||||||
|
map (n: {
|
||||||
|
name = n;
|
||||||
|
uuidFile = config.sops.secrets."sing-box/users/${n}/uuid".path;
|
||||||
|
passwordFile = config.sops.secrets."sing-box/users/${n}/password".path;
|
||||||
|
}) cfg.users
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
sops.secrets = (
|
||||||
|
builtins.foldl' (a: b: a // b) { } (
|
||||||
|
map (u: {
|
||||||
|
"sing-box/users/${u}/uuid" = { };
|
||||||
|
"sing-box/users/${u}/password" = { };
|
||||||
|
}) cfg.users
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue