-
Notifications
You must be signed in to change notification settings - Fork 262
Open
Description
Calling ipt.StructuredStats("nat", "POSTROUTING")
when rules have negated ranges can error:
invalid CIDR address: !192.168.122.0/24%!(EXTRA string=could not parse destination)
On my machine, I set up a virtual bridge for this subnet, and these iptables rules were auto-created:
ifconfig virbr0; \
sudo iptables -L | grep 192.168; \
sudo iptables -t nat -L POSTROUTING | grep 192.168 \
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 06:79:79:15:1a:de txqueuelen 1000 (Ethernet)
RX packets 76642 bytes 4332785 (4.3 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 476675 bytes 726146534 (726.1 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ACCEPT all -- anywhere 192.168.122.0/24 ctstate RELATED,ESTABLISHED
ACCEPT all -- 192.168.122.0/24 anywhere
RETURN all -- 192.168.122.0/24 base-address.mcast.net/24
RETURN all -- 192.168.122.0/24 255.255.255.255
MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24
ignite
uses this library call to cleanup chains, and these MASQ rules fail to net.ParseCIDR
due to the leading exclamation mark negating the subnet: weaveworks/ignite#393
Here's a minimal reproduction:
Test Code
package main
import (
"fmt"
"github.com/coreos/go-iptables/iptables"
)
// testActual is a forked version of ipt.StructuredStats() that prints debug info
func testActual(ipt *iptables.IPTables) ([]iptables.Stat, error) {
table := "nat"
chain := "POSTROUTING"
rawStats, err := ipt.Stats(table, chain)
if err != nil {
return nil, err
}
structStats := []iptables.Stat{}
for _, rawStat := range rawStats {
fmt.Println(rawStat[7], rawStat[8])
stat, err := ipt.ParseStat(rawStat)
if err != nil {
fmt.Println("rawStat: ", rawStat)
fmt.Println("stat: ", stat)
fmt.Println("err: ", err)
return nil, err
}
structStats = append(structStats, stat)
}
return structStats, nil
}
func minimalReproduction(ipt *iptables.IPTables) (iptables.Stat, error) {
return ipt.ParseStat(
[]string{
"1859",
"112600",
"MASQUERADE",
"tcp",
"--",
"*",
"*",
"192.168.122.0/24",
"!192.168.122.0/24",
"masq ports: 1024-65535",
},
)
}
func main() {
ipt, _ := iptables.NewWithProtocol(iptables.ProtocolIPv4)
fmt.Println("minimalReproduction")
fmt.Println(minimalReproduction(ipt))
fmt.Println()
fmt.Println("testActual")
fmt.Println(testActual(ipt))
}
Test logs:
sudo $(which go) run ./testnet.go
minimalReproduction
{1859 112600 192.168.122.0/24 <nil> } invalid CIDR address: !192.168.122.0/24%!(EXTRA string=could not parse destination)
testActual
172.19.0.0/16 0.0.0.0/0
172.17.0.0/16 0.0.0.0/0
192.168.122.0/24 224.0.0.0/24
192.168.122.0/24 255.255.255.255/32
192.168.122.0/24 !192.168.122.0/24
rawStat: [1883 114040 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535]
stat: {1883 114040 192.168.122.0/24 <nil> }
err: invalid CIDR address: !192.168.122.0/24%!(EXTRA string=could not parse destination)
[] invalid CIDR address: !192.168.122.0/24%!(EXTRA string=could not parse destination)
Metadata
Metadata
Assignees
Labels
No labels