@@ -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
3031func 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.
150218type 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
223322var (
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