diff options
Diffstat (limited to 'modules/tunnel/egress.nix')
| -rw-r--r-- | modules/tunnel/egress.nix | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/modules/tunnel/egress.nix b/modules/tunnel/egress.nix new file mode 100644 index 0000000..7858751 --- /dev/null +++ b/modules/tunnel/egress.nix @@ -0,0 +1,133 @@ +{ + me, + config, + pkgs, + lib, + ... +}: + +let + inherit (lib) findFirst; + + # this is the https port, we use it to try to trick dpi into thinking + # we are just serving normal encrypted web traffic, nothing interesting! :) + # this does mean that our egress servers are unable to support normal www + # services which we put on machines by default, which is okay. + port = 443; + + # supposedly the current gold-standard protocol for circumventing dpi! + # both xray (egress-side) and sing-box (ingress-side) support various + # other protocols, if roskomnadzor learns to sniff out vless fully. + protocol = "vless"; + + inboundTag = "vless-in"; + outboundTag = "direct-out"; + + definition = import ./definition.nix; + inherit (definition) paths mask; + + path = findFirst ( + p: p.egress == me.name + ) (throw "no egress information found for this server!") paths; + + xrayConfig = { + inbounds = [ + { + inherit port protocol; + tag = inboundTag; + + settings = { + clients = [ + { + id = path.info.uuid; + flow = "xtls-rprx-vision"; + } + ]; + decryption = "none"; + }; + + streamSettings = { + network = "tcp"; + security = "reality"; + realitySettings = { + show = false; + dest = "www.${mask}:443"; + serverNames = [ + "www.${mask}" + mask + ]; + privateKey = "@PRIVATE_KEY@"; + shortIds = [ path.info.short ]; + }; + }; + } + ]; + + # and we're out! + outbounds = [ + { + protocol = "freedom"; + tag = outboundTag; + } + ]; + + routing = { + rules = [ + { + type = "field"; + inboundTag = [ inboundTag ]; + inherit outboundTag; + } + ]; + }; + + log = { + loglevel = "debug"; + }; + }; + + config-file = pkgs.writeText "xray.json" (builtins.toJSON xrayConfig); +in +{ + networking.firewall.allowedTCPPorts = [ port ]; + + age.secrets.egress-key = { + file = path.info.keySecret; + }; + + systemd.services = { + # we have to make an xray config on the fly because + # xray does not like reading secrets from specific files, + # it wants them in plain-text! + generate-xray-config = { + description = "Generate Xray configuration"; + wantedBy = [ "multi-user.target" ]; + before = [ "xray.service" ]; + partOf = [ "xray.service" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + mkdir -p /run/xray-configuration + cp ${config-file} /run/xray-configuration/xray.json + + egress_key=$(cat ${config.age.secrets.egress-key.path}) + + # use sd for replacement as a fancy new tool for this + ${pkgs.sd}/bin/sd "@PRIVATE_KEY@" "$egress_key" /run/xray-configuration/xray.json + ''; + }; + + xray = { + requires = [ "generate-xray-config.service" ]; + after = [ "generate-xray-config.service" ]; + restartTriggers = [ config-file ]; + }; + }; + + services.xray = { + enable = true; + settingsFile = "/run/xray-configuration/xray.json"; + }; +} |
