|
44 | 44 |
|
45 | 45 | // Chain defines the iptables chain. |
46 | 46 | type Chain struct { |
47 | | - Name string |
48 | | - Bridge string |
49 | | - Table Table |
| 47 | + Name string |
| 48 | + Bridge string |
| 49 | + Table Table |
| 50 | + HairpinMode bool |
50 | 51 | } |
51 | 52 |
|
52 | 53 | // ChainError is returned to represent errors during ip table operation. |
@@ -75,9 +76,10 @@ func initCheck() error { |
75 | 76 | // NewChain adds a new chain to ip table. |
76 | 77 | func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error) { |
77 | 78 | c := &Chain{ |
78 | | - Name: name, |
79 | | - Bridge: bridge, |
80 | | - Table: table, |
| 79 | + Name: name, |
| 80 | + Bridge: bridge, |
| 81 | + Table: table, |
| 82 | + HairpinMode: hairpinMode, |
81 | 83 | } |
82 | 84 |
|
83 | 85 | if string(c.Table) == "" { |
@@ -151,12 +153,16 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri |
151 | 153 | // value" by both iptables and ip6tables. |
152 | 154 | daddr = "0/0" |
153 | 155 | } |
154 | | - if output, err := Raw("-t", string(Nat), string(action), c.Name, |
| 156 | + args := []string{"-t", string(Nat), string(action), c.Name, |
155 | 157 | "-p", proto, |
156 | 158 | "-d", daddr, |
157 | 159 | "--dport", strconv.Itoa(port), |
158 | 160 | "-j", "DNAT", |
159 | | - "--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))); err != nil { |
| 161 | + "--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))} |
| 162 | + if !c.HairpinMode { |
| 163 | + args = append(args, "!", "-i", c.Bridge) |
| 164 | + } |
| 165 | + if output, err := Raw(args...); err != nil { |
160 | 166 | return err |
161 | 167 | } else if len(output) != 0 { |
162 | 168 | return ChainError{Chain: "FORWARD", Output: output} |
|
0 commit comments