Skip to content

Commit 61fe152

Browse files
vnxmefrancislavoie
andauthored
caddytls: Caddyfile support for TLS handshake matchers (#6461)
* Caddyfile support for TLS handshake matchers: - caddytls.MatchLocalIP - caddytls.MatchRemoteIP - caddytls.MatchServerName * Caddyfile support for TLS handshake matchers: - fix imports order Co-authored-by: Francis Lavoie <lavofr@gmail.com> --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com>
1 parent 3afa02b commit 61fe152

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

modules/caddytls/matchers.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"go.uber.org/zap"
2626

2727
"github.com/caddyserver/caddy/v2"
28+
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
2829
)
2930

3031
func init() {
@@ -56,6 +57,29 @@ func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool {
5657
return false
5758
}
5859

60+
// UnmarshalCaddyfile sets up the MatchServerName from Caddyfile tokens. Syntax:
61+
//
62+
// sni <domains...>
63+
func (m *MatchServerName) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
64+
for d.Next() {
65+
wrapper := d.Val()
66+
67+
// At least one same-line option must be provided
68+
if d.CountRemainingArgs() == 0 {
69+
return d.ArgErr()
70+
}
71+
72+
*m = append(*m, d.RemainingArgs()...)
73+
74+
// No blocks are supported
75+
if d.NextBlock(d.Nesting()) {
76+
return d.Errf("malformed TLS handshake matcher '%s': blocks are not supported", wrapper)
77+
}
78+
}
79+
80+
return nil
81+
}
82+
5983
// MatchRemoteIP matches based on the remote IP of the
6084
// connection. Specific IPs or CIDR ranges can be specified.
6185
//
@@ -145,6 +169,50 @@ func (MatchRemoteIP) matches(ip netip.Addr, ranges []netip.Prefix) bool {
145169
return false
146170
}
147171

172+
// UnmarshalCaddyfile sets up the MatchRemoteIP from Caddyfile tokens. Syntax:
173+
//
174+
// remote_ip <ranges...>
175+
//
176+
// Note: IPs and CIDRs prefixed with ! symbol are treated as not_ranges
177+
func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
178+
for d.Next() {
179+
wrapper := d.Val()
180+
181+
// At least one same-line option must be provided
182+
if d.CountRemainingArgs() == 0 {
183+
return d.ArgErr()
184+
}
185+
186+
for d.NextArg() {
187+
val := d.Val()
188+
if len(val) > 1 && val[0] == '!' {
189+
prefixes, err := m.parseIPRange(val[1:])
190+
if err != nil {
191+
return err
192+
}
193+
for _, prefix := range prefixes {
194+
m.NotRanges = append(m.NotRanges, prefix.String())
195+
}
196+
} else {
197+
prefixes, err := m.parseIPRange(val)
198+
if err != nil {
199+
return err
200+
}
201+
for _, prefix := range prefixes {
202+
m.Ranges = append(m.Ranges, prefix.String())
203+
}
204+
}
205+
}
206+
207+
// No blocks are supported
208+
if d.NextBlock(d.Nesting()) {
209+
return d.Errf("malformed TLS handshake matcher '%s': blocks are not supported", wrapper)
210+
}
211+
}
212+
213+
return nil
214+
}
215+
148216
// MatchLocalIP matches based on the IP address of the interface
149217
// receiving the connection. Specific IPs or CIDR ranges can be specified.
150218
type MatchLocalIP struct {
@@ -219,11 +287,46 @@ func (MatchLocalIP) matches(ip netip.Addr, ranges []netip.Prefix) bool {
219287
return false
220288
}
221289

290+
// UnmarshalCaddyfile sets up the MatchLocalIP from Caddyfile tokens. Syntax:
291+
//
292+
// local_ip <ranges...>
293+
func (m *MatchLocalIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
294+
for d.Next() {
295+
wrapper := d.Val()
296+
297+
// At least one same-line option must be provided
298+
if d.CountRemainingArgs() == 0 {
299+
return d.ArgErr()
300+
}
301+
302+
for d.NextArg() {
303+
prefixes, err := m.parseIPRange(d.Val())
304+
if err != nil {
305+
return err
306+
}
307+
for _, prefix := range prefixes {
308+
m.Ranges = append(m.Ranges, prefix.String())
309+
}
310+
}
311+
312+
// No blocks are supported
313+
if d.NextBlock(d.Nesting()) {
314+
return d.Errf("malformed TLS handshake matcher '%s': blocks are not supported", wrapper)
315+
}
316+
}
317+
318+
return nil
319+
}
320+
222321
// Interface guards
223322
var (
224323
_ ConnectionMatcher = (*MatchServerName)(nil)
225324
_ ConnectionMatcher = (*MatchRemoteIP)(nil)
226325

227326
_ caddy.Provisioner = (*MatchLocalIP)(nil)
228327
_ ConnectionMatcher = (*MatchLocalIP)(nil)
328+
329+
_ caddyfile.Unmarshaler = (*MatchLocalIP)(nil)
330+
_ caddyfile.Unmarshaler = (*MatchRemoteIP)(nil)
331+
_ caddyfile.Unmarshaler = (*MatchServerName)(nil)
229332
)

0 commit comments

Comments
 (0)