Help with Firewall plugin

Started by sardaukar, December 04, 2021, 04:42:12 PM

Previous topic - Next topic
I want to quickly toggle rules between hosts, and the Firewall API plugin seems perfect for it (even though I think this should be part of the normal API, but alas).

This is made more complicated by the fact that the plugin's rules have to be separate from the actual port forwarding rules I'm using. So, I've tried to replicate my SSH redirect to a certain host rule, but I always get a syntax error on the rule.

Here's the original port forward rule:

https://imgur.com/a/CJAZfmi

And here's the one in the Firewall -> Automation -> Source NAT section that I'm trying to get to do the same thing:

https://imgur.com/a/FngGR1V

Right off the bat, the "Destination" filter in the Automation rule doesn't allow me to use "WAN Address" like the proper port-forwarding rule. And when I disable the port-forward rule and activate this Automation one, I get syntax errors:


12-04-21 15:31:16 [ There were error(s) loading the rules: /tmp/rules.debug:64: syntax error - The line in question reads [64]: nat on igb1 inet proto TCP from any port any to any port 22 -> 192.168.1.12 port 22 # qoob_ssh ]


What am I doing wrong? Thanks in advance!

Hi,

For port forward you want "Destination NAT".


Cheers,
Franco

Yeah, the Automation plugin doesn't have that - it's either Source NAT or Filter.

Anyway, I fixed it by changing the IP associated with an alias instead. Now all rules are the same, the only difference is what is the content of my `server` alias.

Here's the Ruby script I ended up using:


#!/usr/bin/env ruby

require 'rest-client'
require 'json'
require 'base64'

raise "must provide IP!" unless ARGV.size == 1

ip = ARGV[0]

KEY = "your API key"
SECRET = "your API secret"

ALIAS_UUID = "your alias UUID"
BASE_URL = "https://192.168.1.1:8443/api/firewall"

def empty_alias
  puts "emptying alias..."

  response = RestClient::Request.new(
    method: :post,
    url: "#{BASE_URL}/alias/setItem/#{ALIAS_UUID}",
    verify_ssl: OpenSSL::SSL::VERIFY_NONE,
    headers: {
      "Authorization" => "Basic " + Base64.strict_encode64("#{KEY}:#{SECRET}"),
      content_type: :json
    },
    payload: {
      alias: {
        name: "server",
        content: ""
      }
    }.to_json
  ).execute

  raise "error" unless response.code == 200
end

def set_alias_to(ip)
  puts "setting alias to #{ip} ..."
  response = RestClient::Request.new(
    method: :post,
    url: "#{BASE_URL}/alias_util/add/server",
    verify_ssl: OpenSSL::SSL::VERIFY_NONE,
    headers: {
      "Authorization" => "Basic " + Base64.strict_encode64("#{KEY}:#{SECRET}"),
      content_type: :json
    },
    payload: {
      address: ip
    }.to_json
  ).execute

  raise "error" unless response.code == 200
end

def apply
  puts "reconfiguring..."
  response = RestClient::Request.new(
    method: :post,
    url: "#{BASE_URL}/alias/reconfigure",
    verify_ssl: OpenSSL::SSL::VERIFY_NONE,
    headers: {
      "Authorization" => "Basic " + Base64.strict_encode64("#{KEY}:#{SECRET}"),
      content_type: :json
    },
    payload: {}.to_json
  ).execute

  raise "error" unless response.code == 200
end

empty_alias
set_alias_to(ip)
apply()

puts "done!"


Now I can just `set_server_alias 192.168.1.12` to change its content. Not super awesome, but OPNSense's API is a bit on the terrible side.

I tried to reproduce "from any port any to any port 22" but could not.

You can use "wanip" in the target field and that should do it.


Cheers,
Franco

I find this solution a bit easier to understand than a plugin that introduces yet another layer of rules ::)

I find the aversion a bit peculiar, but you don't see me rolling eyes over it just yet. ;)


Cheers,
Franco

I just think it's poorly structured. Why have core Firewall API functionality in another plugin? Why have it work on separate rules instead of the ones you want to toggle or change? It's needlessly confusing. 

Because it's the closes we've come so far in having a firewall API sponsored. The original customer who helped shape this has moved on since which has you stuck on this I fear.

Remember the open source motto: my problem, someone else's money. ;)


Cheers,
Franco

True that! I'm just not used to this kind of API (I'm a web developer by day). But then again I'm on the Ruby/Elixir camp, which is a bit closer to the present than PHP ;D