You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wg-access-server/internal/services/network.go

89 lines
2.7 KiB
Go

package services
import (
"fmt"
"net"
"github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
)
func ServerVPNIP(cidr string) *net.IPNet {
vpnip, vpnsubnet := MustParseCIDR(cidr)
vpnsubnet.IP = nextIP(vpnip.Mask(vpnsubnet.Mask))
return vpnsubnet
}
func ConfigureRouting(wgIface string, cidr string) error {
// Networking configuration (ip links and route tables)
// to ensure that network traffic in the VPN subnet
// moves through the wireguard interface
link, err := netlink.LinkByName(wgIface)
if err != nil {
return errors.Wrap(err, "failed to find wireguard interface")
}
vpnip := ServerVPNIP(cidr)
logrus.Infof("server VPN subnet IP is %s", vpnip.String())
addr, err := netlink.ParseAddr(vpnip.String())
if err != nil {
return errors.Wrap(err, "failed to parse subnet address")
}
if err := netlink.AddrAdd(link, addr); err != nil {
logrus.Warn(errors.Wrap(err, "failed to add subnet to wireguard interface"))
}
if err := netlink.LinkSetUp(link); err != nil {
logrus.Warn(errors.Wrap(err, "failed to bring wireguard interface up"))
}
return nil
}
func ConfigureForwarding(wgIface string, gatewayIface string, cidr string) error {
// Networking configuration (iptables) configuration
// to ensure that traffic from clients the wireguard interface
// is sent to the provided network interface
ipt, err := iptables.New()
if err != nil {
return errors.Wrap(err, "failed to init iptables")
}
logrus.Infof("iptables rule - accept forwarding traffic from %s to interface %s", gatewayIface, wgIface)
if err := ipt.AppendUnique("filter", "FORWARD", "-i", gatewayIface, "-o", wgIface, "-j", "ACCEPT"); err != nil {
return errors.Wrap(err, "failed to set ip tables rule")
}
logrus.Infof("iptables rule - accept forwarding traffic from %s to interface %s", wgIface, gatewayIface)
if err := ipt.AppendUnique("filter", "FORWARD", "-i", wgIface, "-o", gatewayIface, "-j", "ACCEPT"); err != nil {
return errors.Wrap(err, "failed to set ip tables rule")
}
logrus.Infof("iptables rule - masquerade traffic from %s to interface %s", cidr, gatewayIface)
if err := ipt.AppendUnique("nat", "POSTROUTING", "-s", cidr, "-o", gatewayIface, "-j", "MASQUERADE"); err != nil {
return errors.Wrap(err, "failed to set ip tables rule")
}
return nil
}
func MustParseCIDR(cidr string) (net.IP, *net.IPNet) {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
panic(err)
}
return ip, ipnet
}
func MustParseIP(ip string) net.IP {
netip, _ := MustParseCIDR(fmt.Sprintf("%s/32", ip))
return netip
}
func nextIP(ip net.IP) net.IP {
next := make([]byte, len(ip))
copy(next, ip)
for j := len(next) - 1; j >= 0; j-- {
next[j]++
if next[j] > 0 {
break
}
}
return next
}