Fix: Add a way to differentiate between bind and local address

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2023-11-14 15:55:32 +01:00
parent 14e437b11e
commit e52865a029
Signed by: luzifer
GPG key ID: D91C3E91E4CAD6F5
4 changed files with 31 additions and 22 deletions

View file

@ -63,28 +63,34 @@ healthCheck:
path: /healthz
tls: true
# Local Address and Port describes the IP and Port to bind the service
# to. The Address given is used for the SNAT and therefore should for
# example be the public IP of the machine
localAddr: 203.0.113.1
localPort: 443
# Bind Address and Port describes the IP and Port to bind the service
# to.
bindAddr: 203.0.113.1
bindPort: 443
# Proto describes which protocol should be routed (defaults to tcp)
proto: tcp
# Targets is a list of routing targets which are checked for their
# liveness status and if they are live, they are included in the NAT
# rulesets.
# Each target consists of an Address, a Port and a Weight. The weight
# Each target consists of two Addresses, a Port and a Weight. The weight
# is defined as an integer and increases / decreases the percentage
# of the traffic that specific target will receive. (For example
# setting all weights to 1 will distribute the traffic equally between
# them, setting one to 2 will double the traffic to that target.)
# The localAddr is used for the SNAT to map the source IP.
targets:
- addr: 10.1.2.4
localAddr: 10.1.2.1
port: 443
weight: 1
- addr: 10.1.2.5
localAddr: 10.1.2.1
port: 443
weight: 1
- addr: 10.1.2.6
localAddr: 10.1.2.1
port: 443
weight: 1
```

View file

@ -23,9 +23,9 @@ type (
Service struct {
Name string `yaml:"name"`
HealthCheck ServiceHealthCheck `yaml:"healthCheck"`
LocalAddr string `yaml:"localAddr"`
LocalPort int `yaml:"localPort"`
LocalProto string `yaml:"localProto"`
BindAddr string `yaml:"bindAddr"`
BindPort int `yaml:"bindPort"`
Proto string `yaml:"proto"`
Targets []Target `yaml:"targets"`
}
@ -40,9 +40,10 @@ type (
// Target represents a load-balancing target to route the traffic
// to in case it is deemed alive
Target struct {
Addr string `yaml:"addr"`
Port int `yaml:"port"`
Weight int `yaml:"weight"`
Addr string `yaml:"addr"`
LocalAddr string `yaml:"localAddr"`
Port int `yaml:"port"`
Weight int `yaml:"weight"`
}
)
@ -73,12 +74,12 @@ func Load(fn string) (cf File, err error) {
return cf, nil
}
// Proto evaluates the LocalProto and returns tcp if empty
func (s Service) Proto() string {
if s.LocalProto == "" {
// Protocol evaluates the Proto and returns tcp if empty
func (s Service) Protocol() string {
if s.Proto == "" {
return "tcp"
}
return s.LocalProto
return s.Proto
}
func (t Target) String() string { return fmt.Sprintf("%s:%d", t.Addr, t.Port) }

View file

@ -34,8 +34,9 @@ type (
// with random distribution and given probability
NATTarget struct {
Addr string
BindAddr string
BindPort int
LocalAddr string
LocalPort int
Port int
Proto string
Weight float64
@ -182,8 +183,8 @@ func (c *Client) buildServiceTable(service string, cType chainType) (rules [][]s
"--probability", strconv.FormatFloat(nt.Weight/weightLeft, 'f', probPrecision, probBitsize),
"-p", nt.Proto,
"-d", nt.LocalAddr,
"--dport", strconv.Itoa(nt.LocalPort),
"-d", nt.BindAddr,
"--dport", strconv.Itoa(nt.BindPort),
"-j", "DNAT",
"--to-destination", fmt.Sprintf("%s:%d", nt.Addr, nt.Port),

View file

@ -67,11 +67,12 @@ func (m Monitor) updateRoutingTargets(checker healthcheck.Checker) (err error) {
tgt := iptables.NATTarget{
Addr: t.Addr,
LocalAddr: m.svc.LocalAddr,
LocalPort: m.svc.LocalPort,
BindAddr: m.svc.BindAddr,
BindPort: m.svc.BindPort,
LocalAddr: t.LocalAddr,
Port: t.Port,
Weight: float64(t.Weight),
Proto: m.svc.Proto(),
Proto: m.svc.Protocol(),
}
if err := checker.Check(m.svc.HealthCheck.Settings, t); err != nil {