refuse tls hellos that carry encrypted client hello before squid sees them
This commit is contained in:
parent
de43dac33c
commit
dff662c6b3
1 changed files with 1537 additions and 43 deletions
|
|
@ -88,7 +88,10 @@ let
|
|||
# Every hive defaults the agents' queue address to the queue's name, so the
|
||||
# only hive without one is a hive told to have none. Also the host still
|
||||
# setting the four removed host options; no case on its queue reads them.
|
||||
# It is also the one controller host with `egress.intercept.refuseEch` off,
|
||||
# which the egress cases read.
|
||||
noAgentQueue = hiveWithController {
|
||||
network.egress.intercept.refuseEch = false;
|
||||
deploy.hive-controller.queue.agentNatsUrl = null;
|
||||
c0re.operatorPronouns = "they/them";
|
||||
c0re.contextWindowTokens.sonnet = 900000;
|
||||
|
|
@ -1700,7 +1703,9 @@ let
|
|||
lib.splitString "table bridge hive_egress {" bare.services.hyperhive.network.egress.ruleset
|
||||
);
|
||||
chain = lib.head (
|
||||
lib.splitString "set log_v4" (lib.last (lib.splitString "chain intercept {" inet))
|
||||
lib.splitString "chain intercept_relay {" (
|
||||
lib.head (lib.splitString "set log_v4" (lib.last (lib.splitString "chain intercept {" inet)))
|
||||
)
|
||||
);
|
||||
rules = lib.filter (l: l != "" && l != "}") (map lib.trim (lib.splitString "\n" chain));
|
||||
idx = pat: lib.lists.findFirstIndex (lib.hasInfix pat) 1000 rules;
|
||||
|
|
@ -1714,12 +1719,72 @@ let
|
|||
&& idx ''fib daddr oifname { "hive-br0", "wg-hive" } return'' < idx "tcp dport 80"
|
||||
&& lib.length redirects == 2
|
||||
&& lib.hasInfix "tcp dport 80 counter redirect to :3129" (lib.head redirects)
|
||||
&& lib.hasInfix "tcp dport 443 counter redirect to :3130" (lib.last redirects)
|
||||
# Port 443 goes to the ClientHello relay, not to squid.
|
||||
&& lib.hasInfix "tcp dport 443 counter redirect to :3131" (lib.last redirects)
|
||||
# Only IPv4 that comes in on the bridge is looked at.
|
||||
&& lib.all (l: lib.hasPrefix ''iifname "hive-br0" meta nfproto ipv4 '' l) (lib.drop 1 rules)
|
||||
&& lib.hasInfix "set direct_mac { type ether_addr; }" without
|
||||
&& !(lib.hasInfix "chain intercept" without);
|
||||
}
|
||||
{
|
||||
# With the relay on, port 443 reaches squid through `hive-priv
|
||||
# egress-ech-relay`: its connections (from the pool, carrying the mark)
|
||||
# are DNATed to squid's HTTPS port, the bridge may not send from the
|
||||
# pool, and the unit routes the pool to `lo`. `noAgentQueue` has the
|
||||
# relay off: the redirect then goes straight to squid and none of the
|
||||
# rest is rendered. Its intercept chain is the presence control.
|
||||
name = "the ClientHello relay sits between the redirect and squid, and refuseEch off removes it";
|
||||
ok =
|
||||
let
|
||||
ruleset = m: m.services.hyperhive.network.egress.ruleset;
|
||||
unit = bare.systemd.services.hive-egress-ech-relay;
|
||||
off = noAgentQueue;
|
||||
in
|
||||
lib.hasInfix "chain intercept_relay {" (ruleset bare)
|
||||
&& lib.hasInfix "type nat hook output priority dstnat; policy accept;" (ruleset bare)
|
||||
&& lib.hasInfix "meta nfproto ipv4 ip saddr 198.18.0.0/15 meta mark 0x45434800 tcp dport 443 counter dnat ip to 10.42.0.1:3130" (
|
||||
ruleset bare
|
||||
)
|
||||
&& lib.hasInfix ''iifname "hive-br0" ip saddr 198.18.0.0/15 counter drop'' (ruleset bare)
|
||||
&& lib.hasInfix "egress-ech-relay 10.42.0.1:3131 0x45434800" unit.serviceConfig.ExecStart
|
||||
&& lib.hasInfix "ip route replace local 198.18.0.0/15 dev lo" unit.serviceConfig.ExecStartPre
|
||||
&& lib.elem "multi-user.target" unit.wantedBy
|
||||
# The relay reads the include in which squid finds the `log` agents.
|
||||
&&
|
||||
(unit.environment.HIVE_EGRESS_AGENT_ALLOW or null)
|
||||
== bare.services.hyperhive.deploy.hive-controller.squid.agentAllowFile
|
||||
&& unit.serviceConfig.SupplementaryGroups == [ "squid" ]
|
||||
&& lib.elem 3131 bare.services.hyperhive.network.exposeHostPorts
|
||||
&& lib.hasInfix "chain intercept {" (ruleset off)
|
||||
&& lib.hasInfix "tcp dport 443 counter redirect to :3130" (ruleset off)
|
||||
&& lib.elem 3130 off.services.hyperhive.network.exposeHostPorts
|
||||
&& !(lib.hasInfix "intercept_relay" (ruleset off))
|
||||
&& !(lib.hasInfix "198.18.0.0/15" (ruleset off))
|
||||
&& !(off.systemd.services ? hive-egress-ech-relay)
|
||||
&& !(lib.elem 3131 off.services.hyperhive.network.exposeHostPorts);
|
||||
}
|
||||
{
|
||||
# The relay names a flow's source with the low 17 bits of the agent's
|
||||
# address, which is unique only in a subnet of /15 or smaller. The
|
||||
# boundary is read at /15 (accepted) and /14 (refused); `bare`, a /24, is
|
||||
# the control that the lookup finds nothing otherwise.
|
||||
name = "the ClientHello relay is refused on a bridge subnet larger than a /15";
|
||||
ok =
|
||||
let
|
||||
refused =
|
||||
m:
|
||||
lib.any (
|
||||
a: !a.assertion && lib.hasInfix "bridgePrefixLength must be 15 or more" a.message
|
||||
) m.assertions;
|
||||
in
|
||||
refused (hiveWithController {
|
||||
network.bridgePrefixLength = 14;
|
||||
})
|
||||
&& !(refused (hiveWithController {
|
||||
network.bridgePrefixLength = 15;
|
||||
}))
|
||||
&& !(refused bare);
|
||||
}
|
||||
{
|
||||
# Squid listens on the two intercept ports, peeks and splices and never
|
||||
# decrypts, names the agent of a flow with the helper, refuses a source
|
||||
|
|
|
|||
Loading…
Reference in a new issue