adding gateway routes for peers

This commit is contained in:
afeiszli 2022-08-22 16:44:04 -04:00
parent ec40ea78d3
commit 4d9a07bf00
7 changed files with 159 additions and 7 deletions

View file

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/gravitl/netmaker/netclient/ncutils"
) )
func ipHandlers(r *mux.Router) { func ipHandlers(r *mux.Router) {
@ -38,7 +39,7 @@ func parseIP(r *http.Request) (string, error) {
// Get Public IP from header // Get Public IP from header
ip := r.Header.Get("X-REAL-IP") ip := r.Header.Get("X-REAL-IP")
ipnet := net.ParseIP(ip) ipnet := net.ParseIP(ip)
if ipnet != nil && !ipIsPrivate(ipnet) { if ipnet != nil && !ncutils.IpIsPrivate(ipnet) {
return ip, nil return ip, nil
} }
@ -47,7 +48,7 @@ func parseIP(r *http.Request) (string, error) {
iplist := strings.Split(forwardips, ",") iplist := strings.Split(forwardips, ",")
for _, ip := range iplist { for _, ip := range iplist {
ipnet := net.ParseIP(ip) ipnet := net.ParseIP(ip)
if ipnet != nil && !ipIsPrivate(ipnet) { if ipnet != nil && !ncutils.IpIsPrivate(ipnet) {
return ip, nil return ip, nil
} }
} }
@ -59,14 +60,10 @@ func parseIP(r *http.Request) (string, error) {
} }
ipnet = net.ParseIP(ip) ipnet = net.ParseIP(ip)
if ipnet != nil { if ipnet != nil {
if ipIsPrivate(ipnet) { if ncutils.IpIsPrivate(ipnet) {
return ip, fmt.Errorf("ip is a private address") return ip, fmt.Errorf("ip is a private address")
} }
return ip, nil return ip, nil
} }
return "", fmt.Errorf("no ip found") return "", fmt.Errorf("no ip found")
} }
func ipIsPrivate(ipnet net.IP) bool {
return ipnet.IsPrivate() || ipnet.IsLoopback()
}

View file

@ -12,6 +12,17 @@ import (
// SetPeerRoutes - sets/removes ip routes for each peer on a network // SetPeerRoutes - sets/removes ip routes for each peer on a network
func SetPeerRoutes(iface string, oldPeers map[string]bool, newPeers []wgtypes.PeerConfig) { func SetPeerRoutes(iface string, oldPeers map[string]bool, newPeers []wgtypes.PeerConfig) {
// get the default route
var hasRoute bool
gwIP, gwIface, err := GetDefaultRoute()
if err != nil {
logger.Log(0, "error getting default route:", err.Error())
}
if gwIP != "" && gwIface != "" && err == nil {
hasRoute = true
}
// traverse through all recieved peers // traverse through all recieved peers
for _, peer := range newPeers { for _, peer := range newPeers {
for _, allowedIP := range peer.AllowedIPs { for _, allowedIP := range peer.AllowedIPs {
@ -23,6 +34,13 @@ func SetPeerRoutes(iface string, oldPeers map[string]bool, newPeers []wgtypes.Pe
delete(oldPeers, allowedIP.String()) delete(oldPeers, allowedIP.String())
} }
} }
if hasRoute && !ncutils.IpIsPrivate(peer.Endpoint.IP) {
ipNet, err := ncutils.GetIPNetFromString(peer.Endpoint.IP.String())
if err != nil {
logger.Log(0, "error parsing ip:", err.Error())
}
setRoute(gwIface, &ipNet, gwIP)
}
} }
// traverse through all remaining existing peers // traverse through all remaining existing peers
for i := range oldPeers { for i := range oldPeers {
@ -37,19 +55,55 @@ func SetPeerRoutes(iface string, oldPeers map[string]bool, newPeers []wgtypes.Pe
// SetCurrentPeerRoutes - sets all the current peers // SetCurrentPeerRoutes - sets all the current peers
func SetCurrentPeerRoutes(iface, currentAddr string, peers []wgtypes.PeerConfig) { func SetCurrentPeerRoutes(iface, currentAddr string, peers []wgtypes.PeerConfig) {
// get the default route
var hasRoute bool
gwIP, gwIface, err := GetDefaultRoute()
if err != nil {
logger.Log(0, "error getting default route:", err.Error())
}
if gwIP != "" && gwIface != "" && err == nil {
hasRoute = true
}
// traverse through all recieved peers
for _, peer := range peers { for _, peer := range peers {
for _, allowedIP := range peer.AllowedIPs { for _, allowedIP := range peer.AllowedIPs {
setRoute(iface, &allowedIP, currentAddr) setRoute(iface, &allowedIP, currentAddr)
} }
if hasRoute && !ncutils.IpIsPrivate(peer.Endpoint.IP) {
ipNet, err := ncutils.GetIPNetFromString(peer.Endpoint.IP.String())
if err != nil {
logger.Log(0, "error parsing ip:", err.Error())
}
setRoute(gwIface, &ipNet, gwIP)
}
} }
} }
// FlushPeerRoutes - removes all current peer routes // FlushPeerRoutes - removes all current peer routes
func FlushPeerRoutes(iface, currentAddr string, peers []wgtypes.Peer) { func FlushPeerRoutes(iface, currentAddr string, peers []wgtypes.Peer) {
// get the default route
var hasRoute bool
gwIP, gwIface, err := GetDefaultRoute()
if err != nil {
logger.Log(0, "error getting default route:", err.Error())
}
if gwIP != "" && gwIface != "" && err == nil {
hasRoute = true
}
for _, peer := range peers { for _, peer := range peers {
for _, allowedIP := range peer.AllowedIPs { for _, allowedIP := range peer.AllowedIPs {
deleteRoute(iface, &allowedIP, currentAddr) deleteRoute(iface, &allowedIP, currentAddr)
} }
if hasRoute && !ncutils.IpIsPrivate(peer.Endpoint.IP) {
ipNet, err := ncutils.GetIPNetFromString(peer.Endpoint.IP.String())
if err != nil {
logger.Log(0, "error parsing ip:", err.Error())
}
deleteRoute(gwIface, &ipNet, gwIP)
}
} }
} }

View file

@ -9,6 +9,44 @@ import (
"github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/ncutils"
) )
// GetDefaultRoute - Gets the default route (ip and interface) on a mac machine
func GetDefaultRoute() (string, string, error) {
var ipaddr string
var iface string
var err error
var outLine string
output, err := ncutils.RunCmd("netstat -nr", false)
for _, line := range strings.Split(strings.TrimSuffix(output, "\n"), "\n") {
if strings.Contains(line, "default") {
outLine = line
break
}
}
space := regexp.MustCompile(`\s+`)
outFormatted := space.ReplaceAllString(outLine, " ")
if err != nil {
return ipaddr, iface, err
}
outputSlice := strings.Split(string(outFormatted), " ")
if !strings.Contains(outputSlice[0], "default") {
return ipaddr, iface, fmt.Errorf("could not find default gateway")
}
ipaddr = outputSlice[1]
if err = checkIPAddress(ipaddr); err != nil {
return ipaddr, iface, err
}
iface = outputSlice[3]
return ipaddr, iface, err
}
func checkIPAddress(ip string) error {
if net.ParseIP(ip) == nil {
return fmt.Errorf("IP Address: %s - Invalid", ip)
}
return nil
}
// route -n add -net 10.0.0.0/8 192.168.0.254 // route -n add -net 10.0.0.0/8 192.168.0.254
// networksetup -setadditionalroutes Ethernet 192.168.1.0 255.255.255.0 10.0.0.2 persistent // networksetup -setadditionalroutes Ethernet 192.168.1.0 255.255.255.0 10.0.0.2 persistent
func setRoute(iface string, addr *net.IPNet, address string) error { func setRoute(iface string, addr *net.IPNet, address string) error {

View file

@ -8,6 +8,32 @@ import (
"github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/ncutils"
) )
// GetDefaultRoute - Gets the default route (ip and interface) on a freebsd machine
func GetDefaultRoute() (string, string, error) {
var ipaddr string
var iface string
var err error
output, err := ncutils.RunCmd("route show default", true)
if err != nil {
return ipaddr, iface, err
}
outFormatted := strings.ReplaceAll(output, "\n", "")
if !strings.Contains(outFormatted, "default") && !strings.Contains(outFormatted, "interface:") {
return ipaddr, iface, fmt.Errorf("could not find default gateway")
}
outputSlice := strings.Split(string(outFormatted), " ")
for i, outString := range outputSlice {
if outString == "gateway:" {
ipaddr = outputSlice[i+1]
}
if outString == "interface:" {
iface = outputSlice[i+1]
}
}
return ipaddr, iface, err
}
func setRoute(iface string, addr *net.IPNet, address string) error { func setRoute(iface string, addr *net.IPNet, address string) error {
var err error var err error
_, _ = ncutils.RunCmd("route add -net "+addr.String()+" -interface "+iface, false) _, _ = ncutils.RunCmd("route add -net "+addr.String()+" -interface "+iface, false)

View file

@ -12,6 +12,30 @@ import (
"github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/ncutils"
) )
// GetDefaultRoute - Gets the default route (ip and interface) on a linux machine
func GetDefaultRoute() (string, string, error) {
var ipaddr string
var iface string
var err error
output, err := ncutils.RunCmd("ip route show default", false)
if err != nil {
return ipaddr, iface, err
}
outputSlice := strings.Split(output, " ")
if !strings.Contains(outputSlice[0], "default") {
return ipaddr, iface, fmt.Errorf("could not find default gateway")
}
for i, outString := range outputSlice {
if outString == "via" {
ipaddr = outputSlice[i+1]
}
if outString == "dev" {
iface = outputSlice[i+1]
}
}
return ipaddr, iface, err
}
func setRoute(iface string, addr *net.IPNet, address string) error { func setRoute(iface string, addr *net.IPNet, address string) error {
out, err := ncutils.RunCmd(fmt.Sprintf("ip route get %s", addr.IP.String()), false) out, err := ncutils.RunCmd(fmt.Sprintf("ip route get %s", addr.IP.String()), false)
if err != nil || !strings.Contains(out, iface) { if err != nil || !strings.Contains(out, iface) {

View file

@ -7,6 +7,15 @@ import (
"github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/ncutils"
) )
// GetDefaultRoute - Gets the default route (ip and interface) on a linux machine
func GetDefaultRoute() (string, string, error) {
var ipaddr string
var iface string
var err error
return ipaddr, iface, fmt.Errorf("not written yet on windows")
}
func setRoute(iface string, addr *net.IPNet, address string) error { func setRoute(iface string, addr *net.IPNet, address string) error {
var err error var err error
_, err = ncutils.RunCmd("route ADD "+addr.String()+" "+address, false) _, err = ncutils.RunCmd("route ADD "+addr.String()+" "+address, false)

View file

@ -90,3 +90,7 @@ func IfaceExists(ifacename string) bool {
} }
return false return false
} }
func IpIsPrivate(ipnet net.IP) bool {
return ipnet.IsPrivate() || ipnet.IsLoopback()
}