Merge pull request #13 from danlsgiga/iptables-listen-destination-port
Add listen port option for NAT routing
This commit is contained in:
10
README.md
10
README.md
@@ -52,6 +52,14 @@ 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_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`
|
||||||
|
|
||||||
|
Alternatively, if `gocast_nat=protocol:port` is specified, then GoCast will create NAT rules, via iptables, and map traffic destined to the assigned VIP and the specified `port` to the physical IP and `port`.
|
||||||
|
|
||||||
|
Example: `gocast_nat=tcp:53` and `gocast_nat=udp:53`
|
||||||
|
|
||||||
## Docker support
|
## 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:
|
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:
|
||||||
```
|
```
|
||||||
@@ -65,7 +73,7 @@ Certain orchestration solutions such as Nomad run the docker containers with pub
|
|||||||
|
|
||||||
- Start the service container in host networking mode OR
|
- 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 ?**
|
**Why not just use ExaBGP or something similar ?**
|
||||||
|
|
||||||
|
|||||||
@@ -202,12 +202,18 @@ func (m *MonitorMgr) Remove(appName string) {
|
|||||||
}
|
}
|
||||||
for _, nat := range a.app.Nats {
|
for _, nat := range a.app.Nats {
|
||||||
parts := strings.Split(nat, ":")
|
parts := strings.Split(nat, ":")
|
||||||
if len(parts) != 2 {
|
switch len(parts) {
|
||||||
|
case 3:
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if err := natRule("D", a.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[1]); err != nil {
|
||||||
|
glog.Errorf("Failed to remove app: %s: %v", a.app.Name, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := natRule("D", a.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1]); err != nil {
|
|
||||||
glog.Errorf("Failed to remove app: %s: %v", a.app.Name, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(m.monitors, appName)
|
delete(m.monitors, appName)
|
||||||
@@ -248,12 +254,18 @@ func (m *MonitorMgr) checkCond(am *appMon) error {
|
|||||||
}
|
}
|
||||||
for _, nat := range app.Nats {
|
for _, nat := range app.Nats {
|
||||||
parts := strings.Split(nat, ":")
|
parts := strings.Split(nat, ":")
|
||||||
if len(parts) != 2 {
|
switch len(parts) {
|
||||||
|
case 3:
|
||||||
|
if err := natRule("A", app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[2]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if err := natRule("A", app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[1]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := natRule("A", app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err := m.ctrl.Announce(app.Vip); err != nil {
|
if err := m.ctrl.Announce(app.Vip); err != nil {
|
||||||
return fmt.Errorf("Failed to announce route: %v", err)
|
return fmt.Errorf("Failed to announce route: %v", err)
|
||||||
@@ -315,10 +327,14 @@ func (m *MonitorMgr) CloseAll() {
|
|||||||
deleteLoopback(am.app.Vip.Net)
|
deleteLoopback(am.app.Vip.Net)
|
||||||
for _, nat := range am.app.Nats {
|
for _, nat := range am.app.Nats {
|
||||||
parts := strings.Split(nat, ":")
|
parts := strings.Split(nat, ":")
|
||||||
if len(parts) != 2 {
|
switch len(parts) {
|
||||||
|
case 3:
|
||||||
|
natRule("D", am.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[2])
|
||||||
|
case 2:
|
||||||
|
natRule("D", am.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1], parts[1])
|
||||||
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
natRule("D", am.app.Vip.Net.IP, m.ctrl.localIP, parts[0], parts[1])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,10 +86,10 @@ func deleteLoopback(addr *net.IPNet) error {
|
|||||||
return nil
|
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(
|
cmd := fmt.Sprintf(
|
||||||
"iptables -t nat -%s PREROUTING -p %s -d %s --dport %s -j DNAT --to-destination %s:%s",
|
"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)
|
cmdList := getCmdList(cmd)
|
||||||
_, err := exec.Command(execCmd, cmdList...).Output()
|
_, err := exec.Command(execCmd, cmdList...).Output()
|
||||||
|
|||||||
Reference in New Issue
Block a user