Browse code

Block non exposed port traffic on ingress nw interfaces

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2016/10/05 16:04:05
Showing 2 changed files
... ...
@@ -326,6 +326,21 @@ func (c *ChainInfo) Remove() error {
326 326
 
327 327
 // Exists checks if a rule exists
328 328
 func Exists(table Table, chain string, rule ...string) bool {
329
+	return exists(false, table, chain, rule...)
330
+}
331
+
332
+// ExistsNative behaves as Exists with the difference it
333
+// will always invoke `iptables` binary.
334
+func ExistsNative(table Table, chain string, rule ...string) bool {
335
+	return exists(true, table, chain, rule...)
336
+}
337
+
338
+func exists(native bool, table Table, chain string, rule ...string) bool {
339
+	f := Raw
340
+	if native {
341
+		f = raw
342
+	}
343
+
329 344
 	if string(table) == "" {
330 345
 		table = Filter
331 346
 	}
... ...
@@ -334,7 +349,7 @@ func Exists(table Table, chain string, rule ...string) bool {
334 334
 
335 335
 	if supportsCOpt {
336 336
 		// if exit status is 0 then return true, the rule exists
337
-		_, err := Raw(append([]string{"-t", string(table), "-C", chain}, rule...)...)
337
+		_, err := f(append([]string{"-t", string(table), "-C", chain}, rule...)...)
338 338
 		return err == nil
339 339
 	}
340 340
 
... ...
@@ -935,6 +935,14 @@ func redirecter() {
935 935
 		rule := strings.Fields(fmt.Sprintf("-t nat -A PREROUTING -d %s -p %s --dport %d -j REDIRECT --to-port %d",
936 936
 			eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, iPort.TargetPort))
937 937
 		rules = append(rules, rule)
938
+		// Allow only incoming connections to exposed ports
939
+		iRule := strings.Fields(fmt.Sprintf("-I INPUT -d %s -p %s --dport %d -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT",
940
+			eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.TargetPort))
941
+		rules = append(rules, iRule)
942
+		// Allow only outgoing connections from exposed ports
943
+		oRule := strings.Fields(fmt.Sprintf("-I OUTPUT -s %s -p %s --sport %d -m conntrack --ctstate ESTABLISHED -j ACCEPT",
944
+			eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.TargetPort))
945
+		rules = append(rules, oRule)
938 946
 	}
939 947
 
940 948
 	ns, err := netns.GetFromPath(os.Args[1])
... ...
@@ -952,7 +960,31 @@ func redirecter() {
952 952
 	for _, rule := range rules {
953 953
 		if err := iptables.RawCombinedOutputNative(rule...); err != nil {
954 954
 			logrus.Errorf("setting up rule failed, %v: %v", rule, err)
955
-			os.Exit(5)
955
+			os.Exit(6)
956
+		}
957
+	}
958
+
959
+	if len(ingressPorts) == 0 {
960
+		return
961
+	}
962
+
963
+	// Ensure blocking rules for anything else in/to ingress network
964
+	for _, rule := range [][]string{
965
+		{"-d", eIP.String(), "-p", "udp", "-j", "DROP"},
966
+		{"-d", eIP.String(), "-p", "tcp", "-j", "DROP"},
967
+	} {
968
+		if !iptables.ExistsNative(iptables.Filter, "INPUT", rule...) {
969
+			if err := iptables.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil {
970
+				logrus.Errorf("setting up rule failed, %v: %v", rule, err)
971
+				os.Exit(7)
972
+			}
973
+		}
974
+		rule[0] = "-s"
975
+		if !iptables.ExistsNative(iptables.Filter, "OUTPUT", rule...) {
976
+			if err := iptables.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil {
977
+				logrus.Errorf("setting up rule failed, %v: %v", rule, err)
978
+				os.Exit(8)
979
+			}
956 980
 		}
957 981
 	}
958 982
 }