tcp stream (und damit: tls passthrough) ist implementiert

This commit is contained in:
br committed 2026-10-11 01:04:45 +02:00
1 parent 6a5cb95f92
commit fdcd06c93f
16 files changed
+1008 -75

No files matched your search

+33 -7
View File
@@ -24,6 +24,29 @@ var (
// Hosts schränken nicht ein (sie schließen nur aus). Positives HostRegexp
// ist nicht erlaubt, weil sich ein Regex nicht gegen die Lizenz prüfen lässt.
func HostsFromRule(rule string) ([]string, error) {
return hostsFromRule(rule, "host", "hostregexp")
}
// HostsFromSNIRule ist das Gegenstück für TCP-Regeln: Jeder ||-Zweig muss
// durch HostSNI(...) beschränkt sein, HostSNIRegexp ist verboten. Erlaubt
// sind nur explizite Hosts – HostSNI(`*`) und Wildcards ergeben
// ErrUnconstrained.
func HostsFromSNIRule(rule string) ([]string, error) {
hosts, err := hostsFromRule(rule, "hostsni", "hostsniregexp")
if err != nil {
return nil, err
}
for _, h := range hosts {
if strings.Contains(h, "*") {
return nil, fmt.Errorf("%w: %q ist kein expliziter Host", ErrUnconstrained, h)
}
}
return hosts, nil
}
// hostsFromRule parst rule; hostMatcher/regexpMatcher sind die Matcher-Namen
// in Kleinschreibung.
func hostsFromRule(rule, hostMatcher, regexpMatcher string) ([]string, error) {
toks, err := lex(rule)
if err != nil {
return nil, err
@@ -36,7 +59,8 @@ func HostsFromRule(rule string) ([]string, error) {
if p.peek().kind != tEOF {
return nil, p.errorf("unerwartetes %q", p.peek().text)
}
constrained, hosts, err := analyze(root, true)
a := analyzer{host: hostMatcher, regexp: regexpMatcher}
constrained, hosts, err := a.analyze(root, true)
if err != nil {
return nil, err
}
@@ -48,29 +72,31 @@ func HostsFromRule(rule string) ([]string, error) {
// analyze ermittelt, ob ein Ausdruck auf Hosts beschränkt ist, und sammelt
// die Hosts aus positiven (nicht negierten) Host-Matchern.
func analyze(n *node, positive bool) (constrained bool, hosts []string, err error) {
type analyzer struct{ host, regexp string }
func (a analyzer) analyze(n *node, positive bool) (constrained bool, hosts []string, err error) {
switch n.op {
case opCall:
switch strings.ToLower(n.name) {
case "host":
case a.host:
if positive {
return true, n.args, nil
}
case "hostregexp":
case a.regexp:
if positive {
return false, nil, ErrHostRegexp
}
}
return false, nil, nil
case opNot:
_, h, err := analyze(n.kids[0], !positive)
_, h, err := a.analyze(n.kids[0], !positive)
return false, h, err
default: // opAnd, opOr
c1, h1, err := analyze(n.kids[0], positive)
c1, h1, err := a.analyze(n.kids[0], positive)
if err != nil {
return false, nil, err
}
c2, h2, err := analyze(n.kids[1], positive)
c2, h2, err := a.analyze(n.kids[1], positive)
if err != nil {
return false, nil, err
}