2020-07-11 21:03:55 +00:00
|
|
|
package firewall
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2021-07-23 19:12:16 +00:00
|
|
|
func (c *Config) SetEnabled(ctx context.Context, enabled bool) (err error) {
|
2020-07-11 21:03:55 +00:00
|
|
|
c.stateMutex.Lock()
|
|
|
|
|
defer c.stateMutex.Unlock()
|
|
|
|
|
|
|
|
|
|
if enabled == c.enabled {
|
|
|
|
|
if enabled {
|
|
|
|
|
c.logger.Info("already enabled")
|
|
|
|
|
} else {
|
|
|
|
|
c.logger.Info("already disabled")
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !enabled {
|
|
|
|
|
c.logger.Info("disabling...")
|
|
|
|
|
if err = c.disable(ctx); err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("disabling firewall: %w", err)
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
c.enabled = false
|
|
|
|
|
c.logger.Info("disabled successfully")
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.logger.Info("enabling...")
|
|
|
|
|
|
|
|
|
|
if err := c.enable(ctx); err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("enabling firewall: %w", err)
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
c.enabled = true
|
|
|
|
|
c.logger.Info("enabled successfully")
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-23 19:12:16 +00:00
|
|
|
func (c *Config) disable(ctx context.Context) (err error) {
|
2020-07-11 21:03:55 +00:00
|
|
|
if err = c.clearAllRules(ctx); err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("clearing all rules: %w", err)
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
2021-04-19 09:24:46 -04:00
|
|
|
if err = c.setIPv4AllPolicies(ctx, "ACCEPT"); err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("setting ipv4 policies: %w", err)
|
2021-04-19 09:24:46 -04:00
|
|
|
}
|
|
|
|
|
if err = c.setIPv6AllPolicies(ctx, "ACCEPT"); err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("setting ipv6 policies: %w", err)
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 02:45:28 +00:00
|
|
|
// To use in defered call when enabling the firewall.
|
2021-07-23 19:12:16 +00:00
|
|
|
func (c *Config) fallbackToDisabled(ctx context.Context) {
|
2020-07-11 21:03:55 +00:00
|
|
|
if ctx.Err() != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-04-19 09:24:46 -04:00
|
|
|
if err := c.disable(ctx); err != nil {
|
|
|
|
|
c.logger.Error("failed reversing firewall changes: " + err.Error())
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-23 19:12:16 +00:00
|
|
|
func (c *Config) enable(ctx context.Context) (err error) {
|
2021-04-19 09:24:46 -04:00
|
|
|
touched := false
|
|
|
|
|
if err = c.setIPv4AllPolicies(ctx, "DROP"); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2021-04-19 09:24:46 -04:00
|
|
|
}
|
|
|
|
|
touched = true
|
|
|
|
|
|
|
|
|
|
if err = c.setIPv6AllPolicies(ctx, "DROP"); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const remove = false
|
|
|
|
|
|
|
|
|
|
defer func() {
|
2021-04-19 09:24:46 -04:00
|
|
|
if touched && err != nil {
|
2020-07-11 21:03:55 +00:00
|
|
|
c.fallbackToDisabled(ctx)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Loopback traffic
|
|
|
|
|
if err = c.acceptInputThroughInterface(ctx, "lo", remove); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
if err = c.acceptOutputThroughInterface(ctx, "lo", remove); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err = c.acceptEstablishedRelatedTraffic(ctx, remove); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
2022-03-13 13:26:09 +00:00
|
|
|
|
|
|
|
|
if err = c.allowVPNIP(ctx); err != nil {
|
|
|
|
|
return err
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
2020-10-24 18:05:11 -04:00
|
|
|
|
2021-04-10 03:08:20 +10:00
|
|
|
for _, network := range c.localNetworks {
|
2023-04-27 13:41:05 +00:00
|
|
|
if err := c.acceptOutputFromIPToSubnet(ctx, network.InterfaceName, network.IP, network.IPNet, remove); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2021-04-10 03:08:20 +10:00
|
|
|
}
|
2022-09-14 02:18:10 +02:00
|
|
|
if err = c.acceptIpv6MulticastOutput(ctx, network.InterfaceName, remove); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2020-11-06 02:54:27 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-13 13:26:09 +00:00
|
|
|
if err = c.allowOutboundSubnets(ctx); err != nil {
|
|
|
|
|
return err
|
2020-10-29 19:23:44 -04:00
|
|
|
}
|
|
|
|
|
|
2020-10-24 18:05:11 -04:00
|
|
|
// Allows packets from any IP address to go through eth0 / local network
|
|
|
|
|
// to reach Gluetun.
|
2021-04-10 03:08:20 +10:00
|
|
|
for _, network := range c.localNetworks {
|
2023-04-27 13:41:05 +00:00
|
|
|
if err := c.acceptInputToSubnet(ctx, network.InterfaceName, network.IPNet, remove); err != nil {
|
2022-02-20 02:58:16 +00:00
|
|
|
return err
|
2021-04-10 03:08:20 +10:00
|
|
|
}
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-13 13:26:09 +00:00
|
|
|
if err = c.allowInputPorts(ctx); err != nil {
|
|
|
|
|
return err
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
2021-07-23 16:06:19 +00:00
|
|
|
if err := c.runUserPostRules(ctx, c.customRulesPath, remove); err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("running user defined post firewall rules: %w", err)
|
2020-07-11 21:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2022-03-13 13:26:09 +00:00
|
|
|
|
|
|
|
|
func (c *Config) allowVPNIP(ctx context.Context) (err error) {
|
|
|
|
|
if c.vpnConnection.IP == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const remove = false
|
|
|
|
|
for _, defaultRoute := range c.defaultRoutes {
|
|
|
|
|
err = c.acceptOutputTrafficToVPN(ctx, defaultRoute.NetInterface, c.vpnConnection, remove)
|
|
|
|
|
if err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("accepting output traffic through VPN: %w", err)
|
2022-03-13 13:26:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Config) allowOutboundSubnets(ctx context.Context) (err error) {
|
|
|
|
|
for _, subnet := range c.outboundSubnets {
|
|
|
|
|
for _, defaultRoute := range c.defaultRoutes {
|
|
|
|
|
const remove = false
|
|
|
|
|
err := c.acceptOutputFromIPToSubnet(ctx, defaultRoute.NetInterface,
|
|
|
|
|
defaultRoute.AssignedIP, subnet, remove)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Config) allowInputPorts(ctx context.Context) (err error) {
|
|
|
|
|
for port, netInterfaces := range c.allowedInputPorts {
|
|
|
|
|
for netInterface := range netInterfaces {
|
|
|
|
|
const remove = false
|
|
|
|
|
err = c.acceptInputToPort(ctx, netInterface, port, remove)
|
|
|
|
|
if err != nil {
|
2023-04-01 16:53:04 +00:00
|
|
|
return fmt.Errorf("accepting input port %d on interface %s: %w",
|
2022-03-13 13:26:09 +00:00
|
|
|
port, netInterface, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|