Having issues with go-iptables Insert

Greetings all,

I’m new to Go, so please bare with me.

I’m playing with the go-iptables package and am having issues with the Insert function. I’ve written a function in my application which takes a net.IP and a string for the port number as parameters. All that I’d like for the function to do is to insert a firewall rule, but it ain’t working.

Here’s my function:

func AddFirewallRule(sourceIP net.IP, port string) {

  // Get INPUT chain from config
  byteValue := config.GetConfig()
  var inputChain config.Chain
  json.Unmarshal(byteValue, &inputChain)

  var chain = inputChain.InputChain

  // Build rulespec for iptables
  var rulespec string = "--protocol tcp -m tcp -s " + sourceIP.String() + " --dport " + port + " -j ACCEPT"

  // Create new IPTables object
  ipt, err := iptables.New()
  if err != nil {
        fmt.Println(err)
  }

  // Get a list of chains from the "filter" table
  chainList, err := ipt.ListChains("filter")
  if err != nil {
	  fmt.Printf("Chain listing failed: %s", err)
  }

  // Check if input_chain is in the chainList, insert rule if it is.
  for i := 0; i < len(chainList); i++ {
	  if chainList[i] == chain {
		  fmt.Println("Found chain:", chain, "-> Inserting rule for", sourceIP.String(), "\n")

		  err = ipt.Insert("filter", chain, 1, rulespec)
		  if err != nil {
			  fmt.Println(err)
		  }

		  break
	  }
  }
}

Here’s the error I’m getting

Found chain: ufw-before-input → Inserting rule for 10.0.0.100

running [/sbin/iptables -t filter -I ufw-before-input 1 --protocol tcp -m tcp -s 10.0.0.100 --dport 22 -j ACCEPT --wait]: exit status 2: iptables v1.6.0: unknown option “–protocol tcp -m tcp -s 10.0.0.100 --dport 22 -j ACCEPT”
Try iptables -h' or 'iptables --help' for more information.

Running /sbin/iptables -t filter -I ufw-before-input 1 --protocol tcp -m tcp -s 10.0.0.100 --dport 22 -j ACCEPT --wait from the command line inserts the rule without issue. Can anybody spot an obvious mistake here? I’m at a bit of a loss and the package’s documentation is lacking at best.

Thanks in advance!

rulespec is just one string and all of it is considered as one argument. You have to write it like this:

err = ipt.Insert("filter", chain, 1, "--protocoll", "tcp", "-s", sourceIP.String(), .... and the rest of the arguments)

See this go-iptables/iptables/iptables_test.go at main · coreos/go-iptables · GitHub

You, sir are a gentleman and a scholar! That resolved my issue. For reference, here’s the updated function:

func AddFirewallRule(sourceIP net.IP, port string) {

  // Get INPUT chain from config
  byteValue := config.GetConfig()
  var inputChain config.Chain
  json.Unmarshal(byteValue, &inputChain)

  var chain = inputChain.InputChain

  // Create new IPTables object
  ipt, err := iptables.New()
  if err != nil {
	  fmt.Println(err)
  }

  // Get a list of chains from the "filter" table
  chainList, err := ipt.ListChains("filter")
  if err != nil {
	  fmt.Printf("Chain listing failed: %s", err)
  }

  // Check if input_chain is in the chainList, insert rule if it is.
  for i := 0; i < len(chainList); i++ {
	  if chainList[i] == chain {
		  fmt.Println("Found chain:", chain, "-> Inserting rule for", sourceIP.String(), "\n")

		  err = ipt.Insert("filter", chain, 1, "--protocol", "tcp", "-s", sourceIP.String(), "--dport", port, "-j", "ACCEPT")
		  if err != nil {
			  fmt.Println(err)
		  }

		  break
	 }
  }
}
1 Like

Thanks and good work!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.