From f1542981d6495a2c2ae0c5d38c08fe1bed2d77a8 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 16 Mar 2022 13:23:35 -0600 Subject: [PATCH] feat(gocast_nat): Add listen port option --- README.md | 6 +++++- controller/monitor.go | 6 +++--- controller/system.go | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9cc58f5..bca2797 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ GoCast supports consul for automatic service discovery and healthchecking. For t If `gocast_monitor=consul` is specified, then GoCast uses the defined healthchecks in consul as the health monitors for the service. +If `gocast_nat=protocol:listenPort:destinationPort` is specified, then GoCast will create NAT rules, via iptables, and map traffic destined to the assigned VIP and the specified `listenport` to the physical IP and `destinationport`. + +Example: `gocast_nat=tcp:53:8053` and `gocast_nat=udp:53:8053` + ## Docker support The docker image at mayuresh82/gocast can be used to run GoCast inside a container. In order for GoCast to manipulate the host network stack correctly, the container needs to run with NET_ADMIN capablity and host mode networking. For example: ``` @@ -63,7 +67,7 @@ Certain orchestration solutions such as Nomad run the docker containers with pub - Start the service container in host networking mode OR -- Register NAT rules for your service with GoCast for the required protocol/port(s). GoCast will then create iptables NAT rules that map traffic destined to the assigned VIP to the physical IP address. This is achieved by adding the `nat=protocol:port` tag(s) in consul or the http query. +- Register NAT rules for your service with GoCast for the required protocol/port(s). GoCast will then create iptables NAT rules that map traffic destined to the assigned VIP to the physical IP address. This is achieved by adding the `nat=protocol:listenPort:destinationPort` in the http query or `gocast_nat=protocol:listenPort:destinationPort` tag(s) in consul, as shown in the Consul integration section above. **Why not just use ExaBGP or something similar ?** diff --git a/controller/monitor.go b/controller/monitor.go index 302f755..a6af92b 100644 --- a/controller/monitor.go +++ b/controller/monitor.go @@ -205,7 +205,7 @@ func (m *MonitorMgr) Remove(appName string) { if len(parts) != 2 { continue } - if err := natRule("D", a.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1]); err != nil { + if err := natRule("D", a.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[2]); err != nil { glog.Errorf("Failed to remove app: %s: %v", a.app.Name, err) } } @@ -251,7 +251,7 @@ func (m *MonitorMgr) checkCond(am *appMon) error { if len(parts) != 2 { continue } - if err := natRule("A", app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1]); err != nil { + if err := natRule("A", app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[2]); err != nil { return err } } @@ -318,7 +318,7 @@ func (m *MonitorMgr) CloseAll() { if len(parts) != 2 { continue } - natRule("D", am.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1]) + natRule("D", am.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[2]) } } } diff --git a/controller/system.go b/controller/system.go index a136d1c..96146cc 100644 --- a/controller/system.go +++ b/controller/system.go @@ -86,10 +86,10 @@ func deleteLoopback(addr *net.IPNet) error { return nil } -func natRule(op string, vip, localAddr net.IP, protocol, port string) error { +func natRule(op string, vip, localAddr net.IP, protocol, lport, dport string) error { cmd := fmt.Sprintf( "iptables -t nat -%s PREROUTING -p %s -d %s --dport %s -j DNAT --to-destination %s:%s", - op, protocol, vip.String(), port, localAddr.String(), port, + op, protocol, vip.String(), lport, localAddr.String(), dport, ) cmdList := getCmdList(cmd) _, err := exec.Command(execCmd, cmdList...).Output()