Skip to content

Commit 9dfce0b

Browse files
author
Santhosh Manohar
committed
Allow reachability across services on different networks in the same host
This also allows pubslied services to be accessible from containers on bridge networks on the host Signed-off-by: Santhosh Manohar <santhosh@docker.com>
1 parent 82fb373 commit 9dfce0b

File tree

3 files changed

+73
-5
lines changed

3 files changed

+73
-5
lines changed

controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,9 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
660660
}
661661

662662
joinCluster(network)
663+
if !c.isDistributedControl() {
664+
arrangeIngressFilterRule()
665+
}
663666

664667
return network, nil
665668
}

service_linux.go

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -479,14 +479,19 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
479479
}
480480

481481
chainExists := iptables.ExistChain(ingressChain, iptables.Nat)
482+
filterChainExists := iptables.ExistChain(ingressChain, iptables.Filter)
482483

483484
ingressOnce.Do(func() {
485+
// Flush nat table and filter table ingress chain rules during init if it
486+
// exists. It might contain stale rules from previous life.
484487
if chainExists {
485-
// Flush ingress chain rules during init if it
486-
// exists. It might contain stale rules from
487-
// previous life.
488488
if err := iptables.RawCombinedOutput("-t", "nat", "-F", ingressChain); err != nil {
489-
logrus.Errorf("Could not flush ingress chain rules during init: %v", err)
489+
logrus.Errorf("Could not flush nat table ingress chain rules during init: %v", err)
490+
}
491+
}
492+
if filterChainExists {
493+
if err := iptables.RawCombinedOutput("-F", ingressChain); err != nil {
494+
logrus.Errorf("Could not flush filter table ingress chain rules during init: %v", err)
490495
}
491496
}
492497
})
@@ -497,10 +502,21 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
497502
return fmt.Errorf("failed to create ingress chain: %v", err)
498503
}
499504
}
505+
if !filterChainExists {
506+
if err := iptables.RawCombinedOutput("-N", ingressChain); err != nil {
507+
return fmt.Errorf("failed to create filter table ingress chain: %v", err)
508+
}
509+
}
500510

501511
if !iptables.Exists(iptables.Nat, ingressChain, "-j", "RETURN") {
502512
if err := iptables.RawCombinedOutput("-t", "nat", "-A", ingressChain, "-j", "RETURN"); err != nil {
503-
return fmt.Errorf("failed to add return rule in ingress chain: %v", err)
513+
return fmt.Errorf("failed to add return rule in nat table ingress chain: %v", err)
514+
}
515+
}
516+
517+
if !iptables.Exists(iptables.Filter, ingressChain, "-j", "RETURN") {
518+
if err := iptables.RawCombinedOutput("-A", ingressChain, "-j", "RETURN"); err != nil {
519+
return fmt.Errorf("failed to add return rule to filter table ingress chain: %v", err)
504520
}
505521
}
506522

@@ -512,6 +528,12 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
512528
}
513529
}
514530

531+
if !iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
532+
if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
533+
return fmt.Errorf("failed to add jump rule to %s in filter table forward chain: %v", ingressChain, err)
534+
}
535+
}
536+
515537
oifName, err := findOIFName(gwIP)
516538
if err != nil {
517539
return fmt.Errorf("failed to find gateway bridge interface name for %s: %v", gwIP, err)
@@ -544,6 +566,30 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
544566
}
545567
}
546568

569+
// Filter table rules to allow a published service to be accessible in the local node from..
570+
// 1) service tasks attached to other networks
571+
// 2) unmanaged containers on bridge networks
572+
rule := strings.Fields(fmt.Sprintf("%s %s -m state -p %s --sport %d --state ESTABLISHED,RELATED -j ACCEPT",
573+
addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort))
574+
if err := iptables.RawCombinedOutput(rule...); err != nil {
575+
errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err)
576+
if !isDelete {
577+
return fmt.Errorf("%s", errStr)
578+
}
579+
logrus.Warnf("%s", errStr)
580+
}
581+
582+
rule = strings.Fields(fmt.Sprintf("%s %s -p %s --dport %d -j ACCEPT",
583+
addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort))
584+
if err := iptables.RawCombinedOutput(rule...); err != nil {
585+
errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err)
586+
if !isDelete {
587+
return fmt.Errorf("%s", errStr)
588+
}
589+
590+
logrus.Warnf("%s", errStr)
591+
}
592+
547593
if err := plumbProxy(iPort, isDelete); err != nil {
548594
logrus.Warnf("failed to create proxy for port %d: %v", iPort.PublishedPort, err)
549595
}
@@ -552,6 +598,22 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
552598
return nil
553599
}
554600

601+
// In the filter table FORWARD chain first rule should be to jump to INGRESS-CHAIN
602+
// This chain has the rules to allow access to the published ports for swarm tasks
603+
// from local bridge networks and docker_gwbridge (ie:taks on other swarm netwroks)
604+
func arrangeIngressFilterRule() {
605+
if iptables.ExistChain(ingressChain, iptables.Filter) {
606+
if iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
607+
if err := iptables.RawCombinedOutput("-D", "FORWARD", "-j", ingressChain); err != nil {
608+
logrus.Warnf("failed to delete jump rule to ingressChain in filter table: %v", err)
609+
}
610+
}
611+
if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
612+
logrus.Warnf("failed to add jump rule to ingressChain in filter table: %v", err)
613+
}
614+
}
615+
}
616+
555617
func findOIFName(ip net.IP) (string, error) {
556618
nlh := ns.NlHandle()
557619

service_unsupported.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in
1717

1818
func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
1919
}
20+
21+
func arrangeIngressFilterRule() {
22+
}

0 commit comments

Comments
 (0)