-
Notifications
You must be signed in to change notification settings - Fork 27
/
firewall_linux.go
93 lines (82 loc) · 2.24 KB
/
firewall_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package firewall
import (
"errors"
"net"
"os/exec"
"strings"
"github.com/coreos/go-iptables/iptables"
"github.com/google/nftables"
"github.com/gravitl/netmaker/logger"
"github.com/vishvananda/netlink"
)
const (
TestIPv4 = "1.1.1.1"
TestIPv6 = "2606:4700:4700::1111"
IPv4Network = "0.0.0.0/0"
IPv6Network = "::/0"
)
// newFirewall if supported, returns an iptables manager, otherwise returns a nftables manager
func newFirewall() (firewallController, error) {
var manager firewallController
if isIptablesSupported() {
logger.Log(0, "iptables is supported")
ipv4Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv4)
ipv6Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv6)
manager = &iptablesManager{
ipv4Client: ipv4Client,
ipv6Client: ipv6Client,
ingRules: make(serverrulestable),
engressRules: make(serverrulestable),
}
return manager, nil
}
logger.Log(0, "iptables is not supported, using nftables")
if isNftablesSupported() {
logger.Log(0, "nftables is supported")
manager = &nftablesManager{
conn: &nftables.Conn{},
ingRules: make(serverrulestable),
engressRules: make(serverrulestable),
}
return manager, nil
}
return manager, errors.New("firewall support not found")
}
func isIptablesSupported() bool {
_, err4 := exec.LookPath("iptables")
_, err6 := exec.LookPath("ip6tables")
return (err4 == nil && err6 == nil)
}
func getInterfaceName(dst net.IPNet) (string, error) {
h, err := netlink.NewHandle(0)
if err != nil {
return "", err
}
if dst.String() == IPv4Network || dst.String() == IPv6Network {
dst.IP = net.ParseIP(TestIPv4)
}
routes, err := h.RouteGet(dst.IP)
if err != nil {
if !strings.Contains(err.Error(), "network is unreachable") {
return "", err
}
//if ipv4 address is unreachable, try ipv6 address
dst.IP = net.ParseIP(TestIPv6)
// routes[0] will be default route
routes, err = netlink.RouteGet(dst.IP)
if err != nil {
return "", err
}
}
for _, r := range routes {
iface, err := net.InterfaceByIndex(r.LinkIndex)
if err == nil {
return iface.Name, nil
}
}
return "", errors.New("interface not found for: " + dst.String())
}
func isNftablesSupported() bool {
_, err := exec.LookPath("nft")
return err == nil
}