{# collect interfaces list (with / without captive portal enabled) #} {% set cp_interface_list = [] %} {% set no_cp_interface_list = [] %} {% if helpers.exists('captiveportal') %} {% for intf_key,interface in interfaces.iteritems()%} {% set is_cp=[] %} {% for cp_key,cp_item in captiveportal.iteritems() %} {% if intf_key == cp_item.interface and interface.ipaddr != 'dhcp' %} {% do cp_interface_list.append({'zone':cp_key,'zoneid':cp_item.zoneid,'if':interface.if}) %} {% do is_cp.append(1) %} {% endif %} {% endfor %} {% if not is_cp%} {% do no_cp_interface_list.append(interface) %} {% endif %} {% endfor %} {% else %} {% for intf_key,interface in interfaces.iteritems() %} {% do no_cp_interface_list.append(interface) %} {% endfor %} {% endif %} #====================================================================================== # flush ruleset #====================================================================================== flush #====================================================================================== # define dummynet pipes #====================================================================================== {% if helpers.exists('OPNsense.TrafficShaper.pipes.pipe') %} {% for pipe in OPNsense.TrafficShaper.pipes.pipe %} pipe {{ pipe.number }} config bw {{ pipe.bandwidth }}{{ pipe.bandwidthMetric }}/s {% if pipe.queue %} queue {{ pipe.queue }} {% if pipe.queueMetric != 'slots' %} {{pipe.queueMetric}} {% endif %} {% endif %} {% endfor %} {% endif %} #====================================================================================== # general purpose rules 1...1000 #====================================================================================== add 100 allow pfsync from any to any add 110 allow carp from any to any # layer 2: pass ARP add 120 pass layer2 mac-type arp,rarp # OPNsense requires for WPA add 130 pass layer2 mac-type 0x888e,0x88c7 # PPP Over Ethernet Session Stage/Discovery Stage add 140 pass layer2 mac-type 0x8863,0x8864 # layer 2: block anything else non-IP(v4/v6) add 150 deny layer2 not mac-type ip,ipv6 #====================================================================================== # Allow traffic to this hosts static ip's #====================================================================================== {% for intf_key,interface in interfaces.iteritems() %} {% if intf_key != "wan" and interface.ipaddr != "dhcp" and interface.ipaddr != "" %} add {{loop.index + 1000}} allow udp from any to {{ interface.ipaddr }} dst-port 53 keep-state add {{loop.index + 1000}} allow ip from any to { 255.255.255.255 or {{interface.ipaddr}} } in add {{loop.index + 1000}} allow ip from { 255.255.255.255 or {{interface.ipaddr}} } to any out add {{loop.index + 1000}} allow icmp from { 255.255.255.255 or {{interface.ipaddr}} } to any out icmptypes 0 add {{loop.index + 1000}} allow icmp from any to { 255.255.255.255 or {{interface.ipaddr}} } in icmptypes 8 {% endif %} {% endfor %} {% for item in cp_interface_list %} #=================================================================================== # zone {{item.zone}} ({{item.zoneid}}) configuration #=================================================================================== {# authenticated users ( table 1 + 2 ) #} add {{3000 + item.zoneid|int * 10 + 1 }} skipto {{10001 + item.zoneid|int * 1000 }} ip from table({{6*(item.zoneid|int-1) + 1 }}) to any via {{item.if}} add {{3000 + item.zoneid|int * 10 + 2 }} skipto {{10001 + item.zoneid|int * 1000 }} ip from table({{6*(item.zoneid|int-1) + 1 }}) to any via {{item.if}} {# authenticated hosts ( table 3 + 4 ) #} add {{3000 + item.zoneid|int * 10 + 3 }} skipto {{10001 + item.zoneid|int * 1000 }} ip from table({{6*(item.zoneid|int-1) + 3 }}) to any via {{item.if}} add {{3000 + item.zoneid|int * 10 + 4 }} skipto {{10001 + item.zoneid|int * 1000 }} ip from table({{6*(item.zoneid|int-1) + 3 }}) to any via {{item.if}} {# authenticated mac addresses ( table 5 + 6 ) #} add {{3000 + item.zoneid|int * 10 + 5 }} skipto {{10001 + item.zoneid|int * 1000 }} ip from table({{6*(item.zoneid|int-1) + 5 }}) to any via {{item.if}} add {{3000 + item.zoneid|int * 10 + 6 }} skipto {{10001 + item.zoneid|int * 1000 }} ip from table({{6*(item.zoneid|int-1) + 5 }}) to any via {{item.if}} {% endfor %} #====================================================================================== # redirect non-authenticated clients to captive portal @ local port 8000 + zoneid #====================================================================================== {% for item in cp_interface_list %} add {{5000 + item.zoneid|int }} fwd 127.0.0.1,{{ item.zoneid|int + 8000 }} tcp from any to any dst-port 80 in via {{item.if}} add {{5000 + item.zoneid|int }} allow ip from any to any dst-port 80 via {{item.if}} {% endfor %} #====================================================================================== # accept traffic from all interfaces not used by captive portal #====================================================================================== {% for item in no_cp_interface_list %} add {{6001 + loop.index }} skipto 60000 all from any to any via {{item.if}} {% endfor %} # let the responses from the captive portal web server back out add 6200 pass tcp from any to any out # block everything else (not mentioned before) add 6201 skipto 65534 all from any to any #====================================================================================== # setup zone accounting section #====================================================================================== {% for item in cp_interface_list %} # zone {{item.zone}} ({{item.zoneid}}) add {{ (item.zoneid|int * 1000) + 10001 }} count ip from any to any via {{item.if}} add {{ (item.zoneid|int * 1000) + 10998 }} skipto 30000 all from any to any via {{item.if}} add {{ (item.zoneid|int * 1000) + 10999 }} deny all from any to any not via {{item.if}} {% endfor %} #====================================================================================== # setup accounting section, first rule is counting all CP traffic #====================================================================================== add 30000 set 0 count ip from any to any #====================================================================================== # traffic shaping section, authorized traffic #====================================================================================== add 60000 return via any {% if helpers.exists('OPNsense.TrafficShaper.rules.rule') %} {% for rule in OPNsense.TrafficShaper.rules.rule %} add {{loop.index + 60000}} pipe {{ rule.pipe }} {{ rule.proto }} via {{ rule.interface }} {% endfor %} {% endif %} # pass authorized add 65533 pass ip from any to any # block all unmatched add 65534 deny all from any to any