Skip to content

Commit

Permalink
New ECS modifier option 'add-if-missing' (#389)
Browse files Browse the repository at this point in the history
  • Loading branch information
folbricht authored Jun 22, 2024
1 parent 7ca6554 commit ced15da
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cmd/routedns/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,8 @@ func instantiateGroup(id string, g group, resolvers map[string]rdns.Resolver) er
switch g.ECSOp {
case "add":
f = rdns.ECSModifierAdd(g.ECSAddress, g.ECSPrefix4, g.ECSPrefix6)
case "add-if-missing":
f = rdns.ECSModifierAddIfMissing(g.ECSAddress, g.ECSPrefix4, g.ECSPrefix6)
case "delete":
f = rdns.ECSModifierDelete
case "privacy":
Expand Down
3 changes: 2 additions & 1 deletion doc/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,7 @@ Example config files: [client-blocklist.toml](../cmd/routedns/example-config/cli
A client subnet modifier is used to either remove ECS options from a query, replace/add one, or improve privacy by hiding more bits of the address. The following operation are supported by the subnet modifier:

- `add` - Add an ECS option to a query. If there is one already it is replaced. If no `ecs-address` is provided, the address of the client is used (with `ecs-prefix4` or `ecs-prefix6` applied).
- `add-if-missing` - Add an ECS option to a query if none was provided by the client. If no `ecs-address` is provided, the address of the client is used (with `ecs-prefix4` or `ecs-prefix6` applied).
- `delete` - Remove the ECS option completely from the EDNS0 record.
- `privacy` - Restrict the number of bits in the address to the number in `ecs-prefix4`/`ecs-prefix6`.

Expand All @@ -865,7 +866,7 @@ Client Subnet modifiers are instantiated with `type = "ecs-modifier"` in the gro
Options:

- `resolvers` - Array of upstream resolvers, only one is supported.
- `ecs-op` - Operation to be performed on query options. Either `add`, `delete`, or `privacy`. Does nothing if not specified.
- `ecs-op` - Operation to be performed on query options. Either `add`, `add-if-missing`, `delete`, or `privacy`. Does nothing if not specified.
- `ecs-address` - The address to use in the option. Only used for add operations. If given, will set the address to a fixed value. If missing, the address of the client is used (with the appropriate `ecs-prefix` applied).
- `ecs-prefix4` and `ecs-prefix6` - Source prefix length. Mask for the address. Only used for add and privacy operations.

Expand Down
25 changes: 25 additions & 0 deletions ecs-modifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,31 @@ func ECSModifierAdd(addr net.IP, prefix4, prefix6 uint8) ECSModifierFunc {
}
}

func ECSModifierAddIfMissing(addr net.IP, prefix4, prefix6 uint8) ECSModifierFunc {
addFunc := ECSModifierAdd(addr, prefix4, prefix6)

return func(id string, q *dns.Msg, ci ClientInfo) {
// See if we have an ECS option already
edns0 := q.IsEdns0()
if edns0 != nil {
// Find the ECS option
for _, opt := range edns0.Option {
ecs, ok := opt.(*dns.EDNS0_SUBNET)
if ok {
logger(id, q, ci).WithFields(logrus.Fields{
"addr": ecs.Address,
"mask": ecs.SourceNetmask,
}).Debug("ecs option already present")
return // There's an ECS option already, don't touch it
}
}
}

// No ECS option found, add it
addFunc(id, q, ci)
}
}

func ECSModifierPrivacy(prefix4, prefix6 uint8) ECSModifierFunc {
return func(id string, q *dns.Msg, ci ClientInfo) {
edns0 := q.IsEdns0()
Expand Down

0 comments on commit ced15da

Please sign in to comment.