Skip to content

Commit 81f04e1

Browse files
committed
update dynamic rules
1 parent dca0406 commit 81f04e1

File tree

2 files changed

+96
-73
lines changed

2 files changed

+96
-73
lines changed

internal/firewall/outboundsubnets.go

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,72 @@ import (
66
"net/netip"
77

88
"github.com/qdm12/gluetun/internal/netlink"
9+
"github.com/qdm12/gluetun/internal/subnet"
910
)
1011

11-
// SetOutboundSubnets sets the outbound subnets to allow.
12-
func (c *Config) SetOutboundSubnets(ctx context.Context, subnets []netip.Prefix, remove bool) (err error) {
12+
func (c *Config) SetOutboundSubnets(ctx context.Context, subnets []netip.Prefix) (err error) {
1313
c.stateMutex.Lock()
1414
defer c.stateMutex.Unlock()
1515

1616
if !c.enabled {
17-
c.outboundSubnets = subnets
17+
c.logger.Info("firewall disabled, only updating allowed subnets internal list")
18+
c.outboundSubnets = make([]netip.Prefix, len(subnets))
19+
copy(c.outboundSubnets, subnets)
1820
return nil
1921
}
2022

21-
c.outboundSubnets = subnets
23+
c.logger.Info("setting allowed subnets...")
2224

23-
if err := c.setOutboundSubnets(ctx, subnets, remove); err != nil {
24-
return err
25+
subnetsToAdd, subnetsToRemove := subnet.FindSubnetsToChange(c.outboundSubnets, subnets)
26+
if len(subnetsToAdd) == 0 && len(subnetsToRemove) == 0 {
27+
return nil
28+
}
29+
30+
c.removeOutboundSubnets(ctx, subnetsToRemove)
31+
if err := c.addOutboundSubnets(ctx, subnetsToAdd); err != nil {
32+
return fmt.Errorf("setting allowed outbound subnets: %w", err)
2533
}
2634

27-
// Apply custom rules after setting outbound subnets
28-
if err := c.runUserPostRules(ctx, c.customRulesPath, remove); err != nil {
35+
// Apply user-defined post firewall rules
36+
if err := c.runUserPostRules(ctx, c.customRulesPath, false); err != nil {
2937
return fmt.Errorf("running user defined post firewall rules: %w", err)
3038
}
3139

3240
return nil
3341
}
3442

35-
func (c *Config) setOutboundSubnets(ctx context.Context, subnets []netip.Prefix, remove bool) (err error) {
36-
// Remove old outbound subnets
37-
for _, subnet := range c.outboundSubnets {
38-
subnetIsIPv6 := subnet.Addr().Is6()
43+
func (c *Config) removeOutboundSubnets(ctx context.Context, subnets []netip.Prefix) {
44+
const remove = true
45+
for _, subNet := range subnets {
46+
subnetIsIPv6 := subNet.Addr().Is6()
47+
firewallUpdated := false
3948
for _, defaultRoute := range c.defaultRoutes {
4049
defaultRouteIsIPv6 := defaultRoute.Family == netlink.FamilyV6
4150
ipFamilyMatch := subnetIsIPv6 == defaultRouteIsIPv6
4251
if !ipFamilyMatch {
4352
continue
4453
}
4554

55+
firewallUpdated = true
4656
err := c.acceptOutputFromIPToSubnet(ctx, defaultRoute.NetInterface,
47-
defaultRoute.AssignedIP, subnet, remove)
57+
defaultRoute.AssignedIP, subNet, remove)
4858
if err != nil {
49-
return err
59+
c.logger.Error("cannot remove outdated outbound subnet: " + err.Error())
60+
continue
5061
}
5162
}
52-
}
5363

54-
// Set new outbound subnets
55-
c.outboundSubnets = subnets
64+
if !firewallUpdated {
65+
c.logIgnoredSubnetFamily(subNet)
66+
continue
67+
}
68+
c.outboundSubnets = subnet.RemoveSubnetFromSubnets(c.outboundSubnets, subNet)
69+
}
70+
}
5671

57-
// Add new outbound subnets
58-
for _, subnet := range c.outboundSubnets {
72+
func (c *Config) addOutboundSubnets(ctx context.Context, subnets []netip.Prefix) error {
73+
const remove = false
74+
for _, subnet := range subnets {
5975
subnetIsIPv6 := subnet.Addr().Is6()
6076
firewallUpdated := false
6177
for _, defaultRoute := range c.defaultRoutes {
@@ -64,8 +80,8 @@ func (c *Config) setOutboundSubnets(ctx context.Context, subnets []netip.Prefix,
6480
if !ipFamilyMatch {
6581
continue
6682
}
67-
firewallUpdated = true
6883

84+
firewallUpdated = true
6985
err := c.acceptOutputFromIPToSubnet(ctx, defaultRoute.NetInterface,
7086
defaultRoute.AssignedIP, subnet, remove)
7187
if err != nil {
@@ -75,8 +91,9 @@ func (c *Config) setOutboundSubnets(ctx context.Context, subnets []netip.Prefix,
7591

7692
if !firewallUpdated {
7793
c.logIgnoredSubnetFamily(subnet)
94+
continue
7895
}
96+
c.outboundSubnets = append(c.outboundSubnets, subnet)
7997
}
80-
8198
return nil
8299
}

internal/firewall/ports.go

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,87 +3,93 @@ package firewall
33
import (
44
"context"
55
"fmt"
6+
"strconv"
67
)
78

8-
// SetAllowedPort sets a port to be allowed for incoming traffic.
9-
func (c *Config) SetAllowedPort(ctx context.Context, port uint16, remove bool) (err error) {
9+
func (c *Config) SetAllowedPort(ctx context.Context, port uint16, intf string) (err error) {
1010
c.stateMutex.Lock()
1111
defer c.stateMutex.Unlock()
1212

13+
if port == 0 {
14+
return nil
15+
}
16+
1317
if !c.enabled {
18+
c.logger.Info("firewall disabled, only updating allowed ports internal state")
19+
existingInterfaces, ok := c.allowedInputPorts[port]
20+
if !ok {
21+
existingInterfaces = make(map[string]struct{})
22+
}
23+
existingInterfaces[intf] = struct{}{}
24+
c.allowedInputPorts[port] = existingInterfaces
1425
return nil
1526
}
1627

17-
if err := c.setAllowedPort(ctx, port, remove); err != nil {
18-
return err
28+
netInterfaces, has := c.allowedInputPorts[port]
29+
if !has {
30+
netInterfaces = make(map[string]struct{})
31+
} else if _, exists := netInterfaces[intf]; exists {
32+
return nil
1933
}
2034

21-
// Apply custom rules after setting allowed port
22-
if err := c.runUserPostRules(ctx, c.customRulesPath, remove); err != nil {
35+
c.logger.Info("setting allowed input port " + fmt.Sprint(port) + " through interface " + intf + "...")
36+
37+
const remove = false
38+
if err := c.acceptInputToPort(ctx, intf, port, remove); err != nil {
39+
return fmt.Errorf("allowing input to port %d through interface %s: %w",
40+
port, intf, err)
41+
}
42+
netInterfaces[intf] = struct{}{}
43+
c.allowedInputPorts[port] = netInterfaces
44+
45+
// Apply user-defined post firewall rules
46+
if err := c.runUserPostRules(ctx, c.customRulesPath, false); err != nil {
2347
return fmt.Errorf("running user defined post firewall rules: %w", err)
2448
}
2549

2650
return nil
2751
}
2852

29-
func (c *Config) setAllowedPort(ctx context.Context, port uint16, remove bool) (err error) {
53+
func (c *Config) RemoveAllowedPort(ctx context.Context, port uint16) (err error) {
3054
c.stateMutex.Lock()
3155
defer c.stateMutex.Unlock()
3256

33-
netInterface := "any" // Assuming "any" is the default interface
57+
if port == 0 {
58+
return nil
59+
}
3460

3561
if !c.enabled {
36-
if remove {
37-
if _, ok := c.allowedInputPorts[port]; !ok {
38-
return nil
39-
}
40-
if _, ok := c.allowedInputPorts[port][netInterface]; !ok {
41-
return nil
42-
}
43-
delete(c.allowedInputPorts[port], netInterface)
44-
if len(c.allowedInputPorts[port]) == 0 {
45-
delete(c.allowedInputPorts, port)
46-
}
47-
} else {
48-
if _, ok := c.allowedInputPorts[port]; !ok {
49-
c.allowedInputPorts[port] = make(map[string]struct{})
50-
}
51-
c.allowedInputPorts[port][netInterface] = struct{}{}
52-
}
62+
c.logger.Info("firewall disabled, only updating allowed ports internal list")
63+
delete(c.allowedInputPorts, port)
5364
return nil
5465
}
5566

56-
if remove {
57-
c.logger.Info(fmt.Sprintf("removing allowed port %d...", port))
58-
if err := c.acceptInputToPort(ctx, netInterface, port, remove); err != nil {
59-
return fmt.Errorf("removing port %d: %w", port, err)
60-
}
61-
if _, ok := c.allowedInputPorts[port]; !ok {
62-
return nil
63-
}
64-
if _, ok := c.allowedInputPorts[port][netInterface]; !ok {
65-
return nil
66-
}
67-
delete(c.allowedInputPorts[port], netInterface)
68-
if len(c.allowedInputPorts[port]) == 0 {
69-
delete(c.allowedInputPorts, port)
70-
}
71-
} else {
72-
if err := c.acceptInputToPort(ctx, netInterface, port, remove); err != nil {
73-
return fmt.Errorf("adding port %d: %w", port, err)
74-
}
75-
if _, ok := c.allowedInputPorts[port]; !ok {
76-
c.allowedInputPorts[port] = make(map[string]struct{})
67+
c.logger.Info("removing allowed port " + strconv.Itoa(int(port)) + "...")
68+
69+
interfacesSet, ok := c.allowedInputPorts[port]
70+
if !ok {
71+
return nil
72+
}
73+
74+
const remove = true
75+
for netInterface := range interfacesSet {
76+
err := c.acceptInputToPort(ctx, netInterface, port, remove)
77+
if err != nil {
78+
return fmt.Errorf("removing allowed port %d on interface %s: %w",
79+
port, netInterface, err)
7780
}
78-
c.allowedInputPorts[port][netInterface] = struct{}{}
81+
delete(interfacesSet, netInterface)
7982
}
8083

81-
return nil
82-
}
84+
// All interfaces were removed successfully, so remove the port entry.
85+
delete(c.allowedInputPorts, port)
8386

84-
// RemoveAllowedPort removes a port from the allowed list for incoming traffic.
85-
func (c *Config) RemoveAllowedPort(ctx context.Context, port uint16) (err error) {
86-
return c.SetAllowedPort(ctx, port, true)
87+
// Apply user-defined post firewall rules
88+
if err := c.runUserPostRules(ctx, c.customRulesPath, false); err != nil {
89+
return fmt.Errorf("running user defined post firewall rules: %w", err)
90+
}
91+
92+
return nil
8793
}
8894

8995
func (c *Config) SetPortRedirection(ctx context.Context, interfaceName string,

0 commit comments

Comments
 (0)