Skip to content

Instantly share code, notes, and snippets.

@eableson
Created August 29, 2023 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eableson/685f54949e224b43cfca8596189811fc to your computer and use it in GitHub Desktop.
Save eableson/685f54949e224b43cfca8596189811fc to your computer and use it in GitHub Desktop.
/user set admin password="<complicated password>"
:global localSubnet "10.248.1.0/24"
:global localIP "10.248.1.254"
:global localDhcpPool "10.248.1.1-10.248.1.99"
:global internalDNS "192.168.10.199,192.168.2.240"
:global zerotierSubnet "10.249.0.0/16"
:global zerotierNetworkID "<zerotier network id>"
# Array of remote subnets to be routed through the zerotier connection
:global routedSubnets { \
{ "192.168.10.0/24"; "office"}; \
{ "192.168.2.0/24"; "house"} \
}
:global wan1Gateway1 "208.67.220.220"; # OpenDNS
:global wan1Gateway2 "1.0.0.1"; # Cloudflare secondary
:global wan1GwRecursive1 "208.67.222.222"; # OpenDNS
:global wan1GwRecursive2 "9.9.9.9"; # Quad 9
:global wan2GwRecursive1 "94.140.14.14"; # AdGuard
:global wan2GwRecursive2 "149.112.112.112"; # Quad 9 Secondary
### Basic bridging setup ###
# Local bridge for internal LAN ports
/interface bridge add name=local
/interface bridge port add interface=ether3 bridge=local
/interface bridge port add interface=ether4 bridge=local
/interface bridge port add interface=ether5 bridge=local
/interface bridge port add interface=ether6 bridge=local
/interface bridge port add interface=ether7 bridge=local
/interface bridge port add interface=ether8 bridge=local
### Interface lists ###
# Setup interface list for both WAN ports to use for firewall rules
/interface list add name=WAN
/interface list member add list=WAN interface=ether1
/interface list member add list=WAN interface=ether2
# Setup interface list for LAN ports to use for firewall rules
/interface list add name=LAN
/interface list member add list=LAN interface=local
# Setup DNS services, required for Zerotier to resolve servers
/ip dns set servers=1.1.1.1,8.8.8.8
# Configure internal LAN network subnet and DHCP
/ip address add address="$localIP/24" interface=local
/ip pool add name=lan_pool ranges=$localDhcpPool
/ip dhcp-server add address-pool=lan_pool disabled=no interface=local lease-time=1h name=dhcp_lan
/ip dhcp-server network add address=$localSubnet dns-server=$internalDNS gateway=$localIP
# Lock down access to the Winbox MAC access
tool mac-server set allowed-interface-list=LAN
tool mac-server mac-winbox set allowed-interface-list=LAN
/ip neighbor discovery-settings set discover-interface-list=LAN
# Basic firewall rules to lock down access from the WAN ports, but allow ping
/ip firewall filter add chain=input connection-state=established,related action=accept comment="accept established,related";
/ip firewall filter add chain=input connection-state=invalid action=drop;
/ip firewall filter add chain=input in-interface-list=WAN protocol=icmp action=accept comment="allow ICMP";
/ip firewall filter add chain=input in-interface-list=WAN action=drop comment="block everything else";
# NAT configuration and security
/ip firewall nat add chain=srcnat out-interface-list=WAN action=masquerade
/ip firewall filter add chain=forward action=fasttrack-connection connection-state=established,related comment="fast-track for established,related";
/ip firewall filter add chain=forward action=accept connection-state=established,related comment="accept established,related";
/ip firewall filter add chain=forward action=drop connection-state=invalid
/ip firewall filter add chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface-list=WAN comment="drop access to clients behind NAT from WAN"
# Configure DHCP on WAN interfaces with script to auto-update the router as required on renewals
/ip dhcp-client add interface=ether1 add-default-route=no script=":if (\$bound=1) do={\r\
\n /ip/route/set [find where comment=\"ISP1\"] gateway=\$\"gateway-address\"\r\
\n}\r\
\n\r\
\n/ip/firewall/connection/remove [find connection-mark=\"ISP1_conn\"]\r\
\n/ip/firewall/connection/remove [find connection-mark=\"ISP2_conn\"]\r\
\n" use-peer-dns=no use-peer-ntp=no
/ip dhcp-client add interface=ether2 add-default-route=no script=":if (\$bound=1) do={\r\
\n /ip/route/set [find where comment=\"ISP2\"] gateway=\$\"gateway-address\"\r\
\n}\r\
\n\r\
\n/ip/firewall/connection/remove [find connection-mark=\"ISP1_conn\"]\r\
\n/ip/firewall/connection/remove [find connection-mark=\"ISP2_conn\"]" use-peer-dns=no use-peer-ntp=no
# Create routing tables for each WAN interface
/routing table add fib name=to_ISP1
/routing table add fib name=to_ISP2
/ip route
# recursive routes for ECMP default gateways, dst-address are public DNS servers
add distance=1 dst-address="$wan1Gateway1/32" gateway=ether1 scope=10 target-scope=10 comment=ISP1
add distance=1 dst-address="$wan1Gateway2/32" gateway=ether2 scope=10 target-scope=10 comment=ISP2
# ECMP default gateways
add check-gateway=ping distance=1 dst-address=0.0.0.0/0 gateway=$wan1Gateway1 scope=10 target-scope=11
add check-gateway=ping distance=1 dst-address=0.0.0.0/0 gateway=$wan1Gateway2 scope=10 target-scope=11
# recursive routes for default gateways, dst-address are public DNS servers
add dst-address="$wan1GwRecursive1/32" gateway=ether1 scope=10 comment="ISP1"
add dst-address="$wan1GwRecursive2/32" gateway=ether1 scope=10 comment="ISP1"
add dst-address="$wan2GwRecursive1/32" gateway=ether2 scope=10 comment="ISP2"
add dst-address="$wan2GwRecursive2/32" gateway=ether2 scope=10 comment="ISP2"
# load-balanced w/ auto failover default gateways
add check-gateway=ping distance=1 dst-address=0.0.0.0/0 gateway=$wan1GwRecursive1 routing-table=to_ISP1 scope=10 target-scope=11
add check-gateway=ping distance=2 dst-address=0.0.0.0/0 gateway=$wan1GwRecursive2 routing-table=to_ISP1 scope=10 target-scope=11
add check-gateway=ping distance=1 dst-address=0.0.0.0/0 gateway=$wan2GwRecursive1 routing-table=to_ISP2 scope=10 target-scope=11
add check-gateway=ping distance=2 dst-address=0.0.0.0/0 gateway=$wan2GwRecursive2 routing-table=to_ISP2 scope=10 target-scope=11
/ip firewall address-list add address=$localSubnet list=local
/ip firewall address-list add address=$zerotierSubnet list=zerotier
:foreach net in=$routedSubnets do={
/ip firewall address-list add address=($net->0) list=($net->1);
}
### Firewall Mangle Rules ###
/ip firewall mangle
add action=accept chain=prerouting comment="bridge access" dst-address-list=local in-interface-list=LAN
# WAN to LAN
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=established,related in-interface=ether1 new-connection-mark=ISP1_conn passthrough=yes
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=established,related in-interface=ether2 new-connection-mark=ISP2_conn passthrough=yes
### PCC mangles ###
# allow direct routes for internal routes
add action=accept chain=prerouting dst-address-list=zerotier
add action=accept chain=prerouting dst-address-list=ztrouted
:foreach net in=$routedSubnets do={
add action=accept chain=prerouting dst-address-list=($net->1);
}
# NAT marks for traffic destined for internet
add action=mark-connection chain=prerouting connection-mark=no-mark dst-address-list=!local dst-address-type=!local in-interface-list=LAN new-connection-mark=ISP1_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:2/0
add action=mark-connection chain=prerouting connection-mark=no-mark dst-address-list=!local dst-address-type=!local in-interface-list=LAN new-connection-mark=ISP2_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:2/1
add action=mark-routing chain=prerouting connection-mark=ISP1_conn in-interface-list=LAN new-routing-mark=to_ISP1 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=ISP2_conn in-interface-list=LAN new-routing-mark=to_ISP2 passthrough=yes
add action=mark-routing chain=output connection-mark=ISP1_conn dst-address-list=!local new-routing-mark=to_ISP1 passthrough=yes
add action=mark-routing chain=output connection-mark=ISP2_conn dst-address-list=!local new-routing-mark=to_ISP2 passthrough=yes
/zerotier/enable zt1
/zerotier/interface/add network=$zerotierNetworkID instance=zt1
:delay 4000ms;
/ip firewall filter add action=accept chain=forward in-interface=zerotier1 place-before=0
/ip firewall filter add action=accept chain=input in-interface=zerotier1 place-before=0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment