2015-12-10 22:35:49 +00:00
|
|
|
package overlay
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"github.com/docker/libnetwork/iptables"
|
|
|
|
)
|
|
|
|
|
|
|
|
const globalChain = "DOCKER-OVERLAY"
|
|
|
|
|
|
|
|
var filterOnce sync.Once
|
|
|
|
|
2015-12-22 18:12:23 +00:00
|
|
|
func chainExists(cname string) bool {
|
2015-12-22 20:23:00 +00:00
|
|
|
if _, err := iptables.Raw("-L", cname); err != nil {
|
2015-12-22 18:12:23 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2015-12-10 22:35:49 +00:00
|
|
|
func setupGlobalChain() {
|
2016-04-13 16:52:25 +00:00
|
|
|
// Because of an ungraceful shutdown, chain could already be present
|
|
|
|
if !chainExists(globalChain) {
|
|
|
|
if err := iptables.RawCombinedOutput("-N", globalChain); err != nil {
|
|
|
|
logrus.Errorf("could not create global overlay chain: %v", err)
|
|
|
|
return
|
|
|
|
}
|
2015-12-10 22:35:49 +00:00
|
|
|
}
|
|
|
|
|
2016-04-13 16:52:25 +00:00
|
|
|
if !iptables.Exists(iptables.Filter, globalChain, "-j", "RETURN") {
|
|
|
|
if err := iptables.RawCombinedOutput("-A", globalChain, "-j", "RETURN"); err != nil {
|
|
|
|
logrus.Errorf("could not install default return chain in the overlay global chain: %v", err)
|
|
|
|
}
|
2015-12-10 22:35:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func setNetworkChain(cname string, remove bool) error {
|
|
|
|
// Initialize the onetime global overlay chain
|
|
|
|
filterOnce.Do(setupGlobalChain)
|
|
|
|
|
2015-12-22 18:12:23 +00:00
|
|
|
exists := chainExists(cname)
|
|
|
|
|
2015-12-10 22:35:49 +00:00
|
|
|
opt := "-N"
|
|
|
|
// In case of remove, make sure to flush the rules in the chain
|
2015-12-22 18:12:23 +00:00
|
|
|
if remove && exists {
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput("-F", cname); err != nil {
|
2015-12-10 22:35:49 +00:00
|
|
|
return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err)
|
|
|
|
}
|
|
|
|
opt = "-X"
|
|
|
|
}
|
|
|
|
|
2015-12-22 18:12:23 +00:00
|
|
|
if (!remove && !exists) || (remove && exists) {
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput(opt, cname); err != nil {
|
2015-12-22 18:12:23 +00:00
|
|
|
return fmt.Errorf("failed network chain operation %q for chain %s: %v", opt, cname, err)
|
|
|
|
}
|
2015-12-10 22:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !remove {
|
2015-12-22 18:12:23 +00:00
|
|
|
if !iptables.Exists(iptables.Filter, cname, "-j", "DROP") {
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput("-A", cname, "-j", "DROP"); err != nil {
|
2015-12-22 18:12:23 +00:00
|
|
|
return fmt.Errorf("failed adding default drop rule to overlay network chain %s: %v", cname, err)
|
|
|
|
}
|
2015-12-10 22:35:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func addNetworkChain(cname string) error {
|
|
|
|
return setNetworkChain(cname, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func removeNetworkChain(cname string) error {
|
|
|
|
return setNetworkChain(cname, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
func setFilters(cname, brName string, remove bool) error {
|
|
|
|
opt := "-I"
|
|
|
|
if remove {
|
|
|
|
opt = "-D"
|
|
|
|
}
|
|
|
|
|
2016-02-23 21:44:38 +00:00
|
|
|
// Every time we set filters for a new subnet make sure to move the global overlay hook to the top of the both the OUTPUT and forward chains
|
2015-12-10 22:35:49 +00:00
|
|
|
if !remove {
|
|
|
|
for _, chain := range []string{"OUTPUT", "FORWARD"} {
|
|
|
|
exists := iptables.Exists(iptables.Filter, chain, "-j", globalChain)
|
|
|
|
if exists {
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput("-D", chain, "-j", globalChain); err != nil {
|
2015-12-10 22:35:49 +00:00
|
|
|
return fmt.Errorf("failed to delete overlay hook in chain %s while moving the hook: %v", chain, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput("-I", chain, "-j", globalChain); err != nil {
|
2015-12-10 22:35:49 +00:00
|
|
|
return fmt.Errorf("failed to insert overlay hook in chain %s: %v", chain, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert/Delete the rule to jump to per-bridge chain
|
|
|
|
exists := iptables.Exists(iptables.Filter, globalChain, "-o", brName, "-j", cname)
|
|
|
|
if (!remove && !exists) || (remove && exists) {
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput(opt, globalChain, "-o", brName, "-j", cname); err != nil {
|
2015-12-10 22:35:49 +00:00
|
|
|
return fmt.Errorf("failed to add per-bridge filter rule for bridge %s, network chain %s: %v", brName, cname, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
exists = iptables.Exists(iptables.Filter, cname, "-i", brName, "-j", "ACCEPT")
|
|
|
|
if (!remove && exists) || (remove && !exists) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-12-15 05:57:56 +00:00
|
|
|
if err := iptables.RawCombinedOutput(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil {
|
2015-12-10 22:35:49 +00:00
|
|
|
return fmt.Errorf("failed to add overlay filter rile for network chain %s, bridge %s: %v", cname, brName, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func addFilters(cname, brName string) error {
|
|
|
|
return setFilters(cname, brName, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func removeFilters(cname, brName string) error {
|
|
|
|
return setFilters(cname, brName, true)
|
|
|
|
}
|