@@ -26,6 +26,7 @@ import (
2626
2727func init () {
2828 reexec .Register ("fwmarker" , fwMarker )
29+ reexec .Register ("redirecter" , redirecter )
2930}
3031
3132func newService (name string , id string , ingressPorts []* PortConfig , aliases []string ) * service {
@@ -275,6 +276,12 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
275276 n := ep .getNetwork ()
276277 eIP := ep .Iface ().Address ()
277278
279+ if n .ingress {
280+ if err := addRedirectRules (sb .Key (), eIP , ep .ingressPorts ); err != nil {
281+ logrus .Errorf ("Failed to add redirect rules for ep %s: %v" , ep .Name (), err )
282+ }
283+ }
284+
278285 if sb .ingress {
279286 // For the ingress sandbox if this is not gateway
280287 // endpoint do nothing.
@@ -380,17 +387,17 @@ func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*P
380387 }
381388
382389 if addService {
383- var iPorts []* PortConfig
390+ var filteredPorts []* PortConfig
384391 if sb .ingress {
385- iPorts = filterPortConfigs (ingressPorts , false )
386- if err := programIngress (gwIP , iPorts , false ); err != nil {
392+ filteredPorts = filterPortConfigs (ingressPorts , false )
393+ if err := programIngress (gwIP , filteredPorts , false ); err != nil {
387394 logrus .Errorf ("Failed to add ingress: %v" , err )
388395 return
389396 }
390397 }
391398
392- logrus .Debugf ("Creating service for vip %s fwMark %d ingressPorts %#v" , vip , fwMark , iPorts )
393- if err := invokeFWMarker (sb .Key (), vip , fwMark , iPorts , eIP , false ); err != nil {
399+ logrus .Debugf ("Creating service for vip %s fwMark %d ingressPorts %#v" , vip , fwMark , ingressPorts )
400+ if err := invokeFWMarker (sb .Key (), vip , fwMark , ingressPorts , eIP , false ); err != nil {
394401 logrus .Errorf ("Failed to add firewall mark rule in sbox %s: %v" , sb .Key (), err )
395402 return
396403 }
@@ -453,15 +460,15 @@ func (sb *sandbox) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po
453460 logrus .Errorf ("Failed to delete a new service for vip %s fwmark %d: %v" , vip , fwMark , err )
454461 }
455462
456- var iPorts []* PortConfig
463+ var filteredPorts []* PortConfig
457464 if sb .ingress {
458- iPorts = filterPortConfigs (ingressPorts , true )
459- if err := programIngress (gwIP , iPorts , true ); err != nil {
465+ filteredPorts = filterPortConfigs (ingressPorts , true )
466+ if err := programIngress (gwIP , filteredPorts , true ); err != nil {
460467 logrus .Errorf ("Failed to delete ingress: %v" , err )
461468 }
462469 }
463470
464- if err := invokeFWMarker (sb .Key (), vip , fwMark , iPorts , eIP , true ); err != nil {
471+ if err := invokeFWMarker (sb .Key (), vip , fwMark , ingressPorts , eIP , true ); err != nil {
465472 logrus .Errorf ("Failed to add firewall mark rule in sbox %s: %v" , sb .Key (), err )
466473 }
467474 }
@@ -715,33 +722,57 @@ func plumbProxy(iPort *PortConfig, isDelete bool) error {
715722 return nil
716723}
717724
725+ func writePortsToFile (ports []* PortConfig ) (string , error ) {
726+ f , err := ioutil .TempFile ("" , "port_configs" )
727+ if err != nil {
728+ return "" , err
729+ }
730+ defer f .Close ()
731+
732+ buf , err := proto .Marshal (& EndpointRecord {
733+ IngressPorts : ports ,
734+ })
735+
736+ n , err := f .Write (buf )
737+ if err != nil {
738+ return "" , err
739+ }
740+
741+ if n < len (buf ) {
742+ return "" , io .ErrShortWrite
743+ }
744+
745+ return f .Name (), nil
746+ }
747+
748+ func readPortsFromFile (fileName string ) ([]* PortConfig , error ) {
749+ buf , err := ioutil .ReadFile (fileName )
750+ if err != nil {
751+ return nil , err
752+ }
753+
754+ var epRec EndpointRecord
755+ err = proto .Unmarshal (buf , & epRec )
756+ if err != nil {
757+ return nil , err
758+ }
759+
760+ return epRec .IngressPorts , nil
761+ }
762+
718763// Invoke fwmarker reexec routine to mark vip destined packets with
719764// the passed firewall mark.
720765func invokeFWMarker (path string , vip net.IP , fwMark uint32 , ingressPorts []* PortConfig , eIP * net.IPNet , isDelete bool ) error {
721766 var ingressPortsFile string
722- if len (ingressPorts ) != 0 {
723- f , err := ioutil .TempFile ("" , "port_configs" )
724- if err != nil {
725- return err
726- }
727767
728- buf , err := proto .Marshal (& EndpointRecord {
729- IngressPorts : ingressPorts ,
730- })
731-
732- n , err := f .Write (buf )
768+ if len (ingressPorts ) != 0 {
769+ var err error
770+ ingressPortsFile , err = writePortsToFile (ingressPorts )
733771 if err != nil {
734- f .Close ()
735772 return err
736773 }
737774
738- if n < len (buf ) {
739- f .Close ()
740- return io .ErrShortWrite
741- }
742-
743- ingressPortsFile = f .Name ()
744- f .Close ()
775+ defer os .Remove (ingressPortsFile )
745776 }
746777
747778 addDelOpt := "-A"
@@ -775,20 +806,12 @@ func fwMarker() {
775806
776807 var ingressPorts []* PortConfig
777808 if os .Args [5 ] != "" {
778- buf , err := ioutil .ReadFile (os .Args [5 ])
809+ var err error
810+ ingressPorts , err = readPortsFromFile (os .Args [5 ])
779811 if err != nil {
780- logrus .Errorf ("Failed to read ports config file: %v" , err )
812+ logrus .Errorf ("Failed reading ingress ports file: %v" , err )
781813 os .Exit (6 )
782814 }
783-
784- var epRec EndpointRecord
785- err = proto .Unmarshal (buf , & epRec )
786- if err != nil {
787- logrus .Errorf ("Failed to unmarshal ports config data: %v" , err )
788- os .Exit (7 )
789- }
790-
791- ingressPorts = epRec .IngressPorts
792815 }
793816
794817 vip := os .Args [2 ]
@@ -801,11 +824,7 @@ func fwMarker() {
801824
802825 rules := [][]string {}
803826 for _ , iPort := range ingressPorts {
804- rule := strings .Fields (fmt .Sprintf ("-t nat %s PREROUTING -p %s --dport %d -j REDIRECT --to-port %d" ,
805- addDelOpt , strings .ToLower (PortConfig_Protocol_name [int32 (iPort .Protocol )]), iPort .PublishedPort , iPort .TargetPort ))
806- rules = append (rules , rule )
807-
808- rule = strings .Fields (fmt .Sprintf ("-t mangle %s PREROUTING -p %s --dport %d -j MARK --set-mark %d" ,
827+ rule := strings .Fields (fmt .Sprintf ("-t mangle %s PREROUTING -p %s --dport %d -j MARK --set-mark %d" ,
809828 addDelOpt , strings .ToLower (PortConfig_Protocol_name [int32 (iPort .Protocol )]), iPort .PublishedPort , fwMark ))
810829 rules = append (rules , rule )
811830 }
@@ -852,3 +871,82 @@ func fwMarker() {
852871 }
853872 }
854873}
874+
875+ func addRedirectRules (path string , eIP * net.IPNet , ingressPorts []* PortConfig ) error {
876+ var ingressPortsFile string
877+
878+ if len (ingressPorts ) != 0 {
879+ var err error
880+ ingressPortsFile , err = writePortsToFile (ingressPorts )
881+ if err != nil {
882+ return err
883+ }
884+ defer os .Remove (ingressPortsFile )
885+ }
886+
887+ cmd := & exec.Cmd {
888+ Path : reexec .Self (),
889+ Args : append ([]string {"redirecter" }, path , eIP .String (), ingressPortsFile ),
890+ Stdout : os .Stdout ,
891+ Stderr : os .Stderr ,
892+ }
893+
894+ if err := cmd .Run (); err != nil {
895+ return fmt .Errorf ("reexec failed: %v" , err )
896+ }
897+
898+ return nil
899+ }
900+
901+ // Redirecter reexec function.
902+ func redirecter () {
903+ runtime .LockOSThread ()
904+ defer runtime .UnlockOSThread ()
905+
906+ if len (os .Args ) < 4 {
907+ logrus .Error ("invalid number of arguments.." )
908+ os .Exit (1 )
909+ }
910+
911+ var ingressPorts []* PortConfig
912+ if os .Args [3 ] != "" {
913+ var err error
914+ ingressPorts , err = readPortsFromFile (os .Args [3 ])
915+ if err != nil {
916+ logrus .Errorf ("Failed reading ingress ports file: %v" , err )
917+ os .Exit (2 )
918+ }
919+ }
920+
921+ eIP , _ , err := net .ParseCIDR (os .Args [2 ])
922+ if err != nil {
923+ logrus .Errorf ("Failed to parse endpoint IP %s: %v" , os .Args [2 ], err )
924+ os .Exit (3 )
925+ }
926+
927+ rules := [][]string {}
928+ for _ , iPort := range ingressPorts {
929+ rule := strings .Fields (fmt .Sprintf ("-t nat -A PREROUTING -d %s -p %s --dport %d -j REDIRECT --to-port %d" ,
930+ eIP .String (), strings .ToLower (PortConfig_Protocol_name [int32 (iPort .Protocol )]), iPort .PublishedPort , iPort .TargetPort ))
931+ rules = append (rules , rule )
932+ }
933+
934+ ns , err := netns .GetFromPath (os .Args [1 ])
935+ if err != nil {
936+ logrus .Errorf ("failed get network namespace %q: %v" , os .Args [1 ], err )
937+ os .Exit (4 )
938+ }
939+ defer ns .Close ()
940+
941+ if err := netns .Set (ns ); err != nil {
942+ logrus .Errorf ("setting into container net ns %v failed, %v" , os .Args [1 ], err )
943+ os .Exit (5 )
944+ }
945+
946+ for _ , rule := range rules {
947+ if err := iptables .RawCombinedOutputNative (rule ... ); err != nil {
948+ logrus .Errorf ("setting up rule failed, %v: %v" , rule , err )
949+ os .Exit (5 )
950+ }
951+ }
952+ }
0 commit comments