|
@@ -3,6 +3,7 @@ package udp
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
"net"
|
|
|
+ "strings"
|
|
|
"syscall"
|
|
|
"time"
|
|
|
|
|
@@ -10,7 +11,7 @@ import (
|
|
|
log "github.com/coreos-inc/rudder/Godeps/_workspace/src/github.com/golang/glog"
|
|
|
|
|
|
"github.com/coreos-inc/rudder/backend"
|
|
|
- "github.com/coreos-inc/rudder/pkg"
|
|
|
+ "github.com/coreos-inc/rudder/pkg/ip"
|
|
|
"github.com/coreos-inc/rudder/subnet"
|
|
|
)
|
|
|
|
|
@@ -18,7 +19,7 @@ const (
|
|
|
encapOverhead = 28 // 20 bytes IP hdr + 8 bytes UDP hdr
|
|
|
)
|
|
|
|
|
|
-func configureIface(ifname string, ipn pkg.IP4Net, mtu int) error {
|
|
|
+func configureIface(ifname string, ipn ip.IP4Net, mtu int) error {
|
|
|
iface, err := net.InterfaceByName(ifname)
|
|
|
if err != nil {
|
|
|
log.Error("Failed to lookup interface ", ifname)
|
|
@@ -55,16 +56,53 @@ func configureIface(ifname string, ipn pkg.IP4Net, mtu int) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func acquireLease(sm *subnet.SubnetManager, pubIP net.IP) (pkg.IP4Net, error) {
|
|
|
+func setupIpMasq(ipn ip.IP4Net, iface string) error {
|
|
|
+ ipt, err := ip.NewIPTables()
|
|
|
+ if err != nil {
|
|
|
+ log.Error("Failed to setup IP Masquerade. iptables was not found")
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ err = ipt.ClearChain("nat", "RUDDER")
|
|
|
+ if err != nil {
|
|
|
+ log.Error("Failed to create/clear RUDDER chain in NAT table: ", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ rules := [][]string{
|
|
|
+ // This rule makes sure we don't NAT traffic within overlay network (e.g. coming out of docker0)
|
|
|
+ []string{ "RUDDER", "-d", ipn.String(), "-j", "ACCEPT" },
|
|
|
+ // This rule makes sure we don't NAT multicast traffic within overlay network
|
|
|
+ []string{ "RUDDER", "-d", "224.0.0.0/4", "-j", "ACCEPT" },
|
|
|
+ // This rule will NAT everything originating from our overlay network and
|
|
|
+ []string{ "RUDDER", "!", "-o", iface, "-j", "MASQUERADE" },
|
|
|
+ // This rule will take everything coming from overlay and sent it to RUDDER chain
|
|
|
+ []string{ "POSTROUTING", "-s", ipn.String(), "-j", "RUDDER" },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, args := range rules {
|
|
|
+ log.Info("Adding iptables rule: ", strings.Join(args, " "))
|
|
|
+
|
|
|
+ err = ipt.AppendUnique("nat", args...)
|
|
|
+ if err != nil {
|
|
|
+ log.Error("Failed to insert IP masquerade rule: ", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func acquireLease(sm *subnet.SubnetManager, pubIP net.IP) (ip.IP4Net, error) {
|
|
|
attrs := subnet.BaseAttrs{
|
|
|
- PublicIP: pkg.FromIP(pubIP),
|
|
|
+ PublicIP: ip.FromIP(pubIP),
|
|
|
}
|
|
|
data, err := json.Marshal(&attrs)
|
|
|
if err != nil {
|
|
|
- return pkg.IP4Net{}, err
|
|
|
+ return ip.IP4Net{}, err
|
|
|
}
|
|
|
|
|
|
- var sn pkg.IP4Net
|
|
|
+ var sn ip.IP4Net
|
|
|
for {
|
|
|
sn, err = sm.AcquireLease(attrs.PublicIP, string(data))
|
|
|
if err == nil {
|
|
@@ -78,14 +116,14 @@ func acquireLease(sm *subnet.SubnetManager, pubIP net.IP) (pkg.IP4Net, error) {
|
|
|
return sn, nil
|
|
|
}
|
|
|
|
|
|
-func Run(sm *subnet.SubnetManager, iface *net.Interface, ip net.IP, port int, fast bool, ready backend.ReadyFunc) {
|
|
|
- sn, err := acquireLease(sm, ip)
|
|
|
+func Run(sm *subnet.SubnetManager, tepIface *net.Interface, tepIP net.IP, port int, ipMasq bool, ready backend.ReadyFunc) {
|
|
|
+ sn, err := acquireLease(sm, tepIP)
|
|
|
if err != nil {
|
|
|
log.Error("Failed to acquire lease: ", err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- tun, tunName, err := pkg.OpenTun("rudder%d")
|
|
|
+ tun, tunName, err := ip.OpenTun("rudder%d")
|
|
|
if err != nil {
|
|
|
log.Error("Failed to open TUN device: ", err)
|
|
|
return
|
|
@@ -103,32 +141,35 @@ func Run(sm *subnet.SubnetManager, iface *net.Interface, ip net.IP, port int, fa
|
|
|
|
|
|
// Interface's subnet is that of the whole overlay network (e.g. /16)
|
|
|
// and not that of the individual host (e.g. /24)
|
|
|
- ipn := pkg.IP4Net{
|
|
|
+ tunNet := ip.IP4Net{
|
|
|
IP: sn.IP,
|
|
|
PrefixLen: sm.GetConfig().Network.PrefixLen,
|
|
|
}
|
|
|
|
|
|
// TUN MTU will be smaller b/c of encap (IP+UDP hdrs)
|
|
|
var mtu int
|
|
|
- if iface.MTU > 0 {
|
|
|
- mtu = iface.MTU - encapOverhead
|
|
|
+ if tepIface.MTU > 0 {
|
|
|
+ mtu = tepIface.MTU - encapOverhead
|
|
|
} else {
|
|
|
- log.Errorf("Failed to determine MTU for %s interface", ip)
|
|
|
+ log.Errorf("Failed to determine MTU for %s interface", tepIP)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- err = configureIface(tunName, ipn, mtu)
|
|
|
+ err = configureIface(tunName, tunNet, mtu)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+ if ipMasq {
|
|
|
+ err = setupIpMasq(tunNet.Network(), tunName)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// all initialized and ready for business
|
|
|
log.Info("UDP encapsulation initialized")
|
|
|
ready(sn, mtu)
|
|
|
|
|
|
- if fast {
|
|
|
- fastProxy(sm, tun, conn, ipn.IP, uint(mtu), port)
|
|
|
- } else {
|
|
|
- proxy(sm, tun, conn, uint(mtu), port)
|
|
|
- }
|
|
|
+ fastProxy(sm, tun, conn, tunNet.IP, uint(mtu), port)
|
|
|
}
|