Files
gluetun/internal/firewall/route.go
Quentin McGaw 64649039d9 Rewrite of the entrypoint in Golang (#71)
- General improvements
    - Parallel download of only needed files at start
    - Prettier console output with all streams merged (openvpn, unbound, shadowsocks etc.)
    - Simplified Docker final image
    - Faster bootup
- DNS over TLS
    - Finer grain blocking at DNS level: malicious, ads and surveillance
    - Choose your DNS over TLS providers
    - Ability to use multiple DNS over TLS providers for DNS split horizon
    - Environment variables for DNS logging
    - DNS block lists needed are downloaded and built automatically at start, in parallel
- PIA
    - A random region is selected if the REGION parameter is left empty (thanks @rorph for your PR)
    - Routing and iptables adjusted so it can work as a Kubernetes pod sidecar (thanks @rorph for your PR)
2020-02-06 20:42:46 -05:00

89 lines
3.2 KiB
Go

package firewall
import (
"encoding/hex"
"net"
"fmt"
"strings"
"github.com/qdm12/private-internet-access-docker/internal/constants"
)
func (c *configurator) AddRoutesVia(subnets []net.IPNet, defaultGateway net.IP, defaultInterface string) error {
for _, subnet := range subnets {
subnetStr := subnet.String()
output, err := c.commander.Run("ip", "route", "show", subnetStr)
if err != nil {
return fmt.Errorf("cannot read route %s: %s: %w", subnetStr, output, err)
} else if len(output) > 0 { // thanks to @npawelek https://github.com/npawelek
continue // already exists
// TODO remove it instead and continue execution below
}
c.logger.Info("%s: adding %s as route via %s", logPrefix, subnetStr, defaultInterface)
output, err = c.commander.Run("ip", "route", "add", subnetStr, "via", defaultGateway.String(), "dev", defaultInterface)
if err != nil {
return fmt.Errorf("cannot add route for %s via %s %s %s: %s: %w", subnetStr, defaultGateway.String(), "dev", defaultInterface, output, err)
}
}
return nil
}
func (c *configurator) GetDefaultRoute() (defaultInterface string, defaultGateway net.IP, defaultSubnet net.IPNet, err error) {
c.logger.Info("%s: detecting default network route", logPrefix)
data, err := c.fileManager.ReadFile(string(constants.NetRoute))
if err != nil {
return "", nil, defaultSubnet, err
}
// Verify number of lines and fields
lines := strings.Split(string(data), "\n")
if len(lines) < 3 {
return "", nil, defaultSubnet, fmt.Errorf("not enough lines (%d) found in %s", len(lines), constants.NetRoute)
}
fieldsLine1 := strings.Fields(lines[1])
if len(fieldsLine1) < 3 {
return "", nil, defaultSubnet, fmt.Errorf("not enough fields in %q", lines[1])
}
fieldsLine2 := strings.Fields(lines[2])
if len(fieldsLine2) < 8 {
return "", nil, defaultSubnet, fmt.Errorf("not enough fields in %q", lines[2])
}
// get information
defaultInterface = fieldsLine1[0]
defaultGateway, err = reversedHexToIPv4(fieldsLine1[2])
if err != nil {
return "", nil, defaultSubnet, err
}
netNumber, err := reversedHexToIPv4(fieldsLine2[1])
if err != nil {
return "", nil, defaultSubnet, err
}
netMask, err := hexToIPv4Mask(fieldsLine2[7])
if err != nil {
return "", nil, defaultSubnet, err
}
subnet := net.IPNet{IP: netNumber, Mask: netMask}
c.logger.Info("%s: default route found: interface %s, gateway %s, subnet %s", logPrefix, defaultInterface, defaultGateway.String(), subnet.String())
return defaultInterface, defaultGateway, subnet, nil
}
func reversedHexToIPv4(reversedHex string) (IP net.IP, err error) {
bytes, err := hex.DecodeString(reversedHex)
if err != nil {
return nil, fmt.Errorf("cannot parse reversed IP hex %q: %s", reversedHex, err)
} else if len(bytes) != 4 {
return nil, fmt.Errorf("hex string contains %d bytes instead of 4", len(bytes))
}
return []byte{bytes[3], bytes[2], bytes[1], bytes[0]}, nil
}
func hexToIPv4Mask(hexString string) (mask net.IPMask, err error) {
bytes, err := hex.DecodeString(hexString)
if err != nil {
return nil, fmt.Errorf("cannot parse hex mask %q: %s", hexString, err)
} else if len(bytes) != 4 {
return nil, fmt.Errorf("hex string contains %d bytes instead of 4", len(bytes))
}
return []byte{bytes[3], bytes[2], bytes[1], bytes[0]}, nil
}