Fix: only run ip6tables if it is supported by the Kernel (#431)
- Fix #430
This commit is contained in:
@@ -42,6 +42,9 @@ type configurator struct { //nolint:maligned
|
|||||||
localIP net.IP
|
localIP net.IP
|
||||||
networkInfoMutex sync.Mutex
|
networkInfoMutex sync.Mutex
|
||||||
|
|
||||||
|
// Fixed state
|
||||||
|
ip6Tables bool
|
||||||
|
|
||||||
// State
|
// State
|
||||||
enabled bool
|
enabled bool
|
||||||
vpnConnection models.OpenVPNConnection
|
vpnConnection models.OpenVPNConnection
|
||||||
@@ -52,12 +55,14 @@ type configurator struct { //nolint:maligned
|
|||||||
|
|
||||||
// NewConfigurator creates a new Configurator instance.
|
// NewConfigurator creates a new Configurator instance.
|
||||||
func NewConfigurator(logger logging.Logger, routing routing.Routing, openFile os.OpenFileFunc) Configurator {
|
func NewConfigurator(logger logging.Logger, routing routing.Routing, openFile os.OpenFileFunc) Configurator {
|
||||||
|
commander := command.NewCommander()
|
||||||
return &configurator{
|
return &configurator{
|
||||||
commander: command.NewCommander(),
|
commander: commander,
|
||||||
logger: logger.NewChild(logging.SetPrefix("firewall: ")),
|
logger: logger.NewChild(logging.SetPrefix("firewall: ")),
|
||||||
routing: routing,
|
routing: routing,
|
||||||
openFile: openFile,
|
openFile: openFile,
|
||||||
allowedInputPorts: make(map[uint16]string),
|
allowedInputPorts: make(map[uint16]string),
|
||||||
|
ip6Tables: ip6tablesSupported(context.Background(), commander),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,22 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/command"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrIP6Tables = errors.New("failed ip6tables command")
|
ErrIP6Tables = errors.New("failed ip6tables command")
|
||||||
|
ErrIP6NotSupported = errors.New("ip6tables not supported")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ip6tablesSupported(ctx context.Context, commander command.Commander) (supported bool) {
|
||||||
|
if _, err := commander.Run(ctx, "ip6tables", "-L"); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (c *configurator) runIP6tablesInstructions(ctx context.Context, instructions []string) error {
|
func (c *configurator) runIP6tablesInstructions(ctx context.Context, instructions []string) error {
|
||||||
for _, instruction := range instructions {
|
for _, instruction := range instructions {
|
||||||
if err := c.runIP6tablesInstruction(ctx, instruction); err != nil {
|
if err := c.runIP6tablesInstruction(ctx, instruction); err != nil {
|
||||||
@@ -21,6 +31,9 @@ func (c *configurator) runIP6tablesInstructions(ctx context.Context, instruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *configurator) runIP6tablesInstruction(ctx context.Context, instruction string) error {
|
func (c *configurator) runIP6tablesInstruction(ctx context.Context, instruction string) error {
|
||||||
|
if !c.ip6Tables {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
c.ip6tablesMutex.Lock() // only one ip6tables command at once
|
c.ip6tablesMutex.Lock() // only one ip6tables command at once
|
||||||
defer c.ip6tablesMutex.Unlock()
|
defer c.ip6tablesMutex.Unlock()
|
||||||
if c.debug {
|
if c.debug {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ var (
|
|||||||
ErrPolicyUnknown = errors.New("unknown policy")
|
ErrPolicyUnknown = errors.New("unknown policy")
|
||||||
ErrClearRules = errors.New("cannot clear all rules")
|
ErrClearRules = errors.New("cannot clear all rules")
|
||||||
ErrSetIPtablesPolicies = errors.New("cannot set iptables policies")
|
ErrSetIPtablesPolicies = errors.New("cannot set iptables policies")
|
||||||
|
ErrNeedIP6Tables = errors.New("ip6tables is required, please upgrade your kernel to support it")
|
||||||
)
|
)
|
||||||
|
|
||||||
func appendOrDelete(remove bool) string {
|
func appendOrDelete(remove bool) string {
|
||||||
@@ -125,6 +126,9 @@ func (c *configurator) acceptInputToSubnet(ctx context.Context, intf string, des
|
|||||||
if isIP4Subnet {
|
if isIP4Subnet {
|
||||||
return c.runIptablesInstruction(ctx, instruction)
|
return c.runIptablesInstruction(ctx, instruction)
|
||||||
}
|
}
|
||||||
|
if !c.ip6Tables {
|
||||||
|
return fmt.Errorf("accept input to subnet %s: %w", destination, ErrNeedIP6Tables)
|
||||||
|
}
|
||||||
return c.runIP6tablesInstruction(ctx, instruction)
|
return c.runIP6tablesInstruction(ctx, instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +153,8 @@ func (c *configurator) acceptOutputTrafficToVPN(ctx context.Context,
|
|||||||
isIPv4 := connection.IP.To4() != nil
|
isIPv4 := connection.IP.To4() != nil
|
||||||
if isIPv4 {
|
if isIPv4 {
|
||||||
return c.runIptablesInstruction(ctx, instruction)
|
return c.runIptablesInstruction(ctx, instruction)
|
||||||
|
} else if !c.ip6Tables {
|
||||||
|
return fmt.Errorf("accept output to VPN server: %w", ErrNeedIP6Tables)
|
||||||
}
|
}
|
||||||
return c.runIP6tablesInstruction(ctx, instruction)
|
return c.runIP6tablesInstruction(ctx, instruction)
|
||||||
}
|
}
|
||||||
@@ -168,6 +174,8 @@ func (c *configurator) acceptOutputFromIPToSubnet(ctx context.Context,
|
|||||||
|
|
||||||
if doIPv4 {
|
if doIPv4 {
|
||||||
return c.runIptablesInstruction(ctx, instruction)
|
return c.runIptablesInstruction(ctx, instruction)
|
||||||
|
} else if !c.ip6Tables {
|
||||||
|
return fmt.Errorf("accept output from %s to %s: %w", sourceIP, destinationSubnet, ErrNeedIP6Tables)
|
||||||
}
|
}
|
||||||
return c.runIP6tablesInstruction(ctx, instruction)
|
return c.runIP6tablesInstruction(ctx, instruction)
|
||||||
}
|
}
|
||||||
@@ -228,9 +236,12 @@ func (c *configurator) runUserPostRules(ctx context.Context, filepath string, re
|
|||||||
rule = flipRule(rule)
|
rule = flipRule(rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ipv4 {
|
switch {
|
||||||
|
case ipv4:
|
||||||
err = c.runIptablesInstruction(ctx, rule)
|
err = c.runIptablesInstruction(ctx, rule)
|
||||||
} else {
|
case !c.ip6Tables:
|
||||||
|
err = fmt.Errorf("cannot run user ip6tables rule: %w", ErrNeedIP6Tables)
|
||||||
|
default: // ipv6
|
||||||
err = c.runIP6tablesInstruction(ctx, rule)
|
err = c.runIP6tablesInstruction(ctx, rule)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user