After run this script you should use terminal:
Add WAN: $WanInOut add <your wan interface> <you local network/bridge>
Remove WAN: $WanInOut remove <your wan interface>
NOTE: If you leave <wan> and <bridge> empty the script will automatically set WAN(s) for every exists pppoe,l2tp,ppp,sstp,ether with dhcp client and lte interfaces, and set BRIDGE(s) for every exists bridge(s).
Code: Select all
:global WanInOut do={
:if ([len $1]=0) do={:error "example: \$WanInOut <add/remove> <wan interface name> <local lan interface name/bridge>";}
:local todo [:tostr $1];
:local wans [:tostr $2];
# If no wan interface input detected
:if ([:len $wans]=0) do={
# search for isp connections
:foreach idn in=[/interface find where type="pppoe-out" and disabled=no or type="l2tp-out" and disabled=no or type="ppp-out" and disabled=no or type="sstp-out" and disabled=no] do={
if ([:typeof $wans]="nothing") do={
:set $wans ([/interface get value-name=name $idn]);
} else={
:set $wans ($wans.",".[/interface get value-name=name $idn]);
}
}
# search for dhcp clients
:foreach idn in=[/ip dhcp-client find where add-default-route="yes" and status="bound" and disabled=no] do={
:if ([/interface get value-name=type $idn]="ether") do={
:if ([:typeof $wans]="nothing") do={
:set $wans ([/ip dhcp-client get value-name=interface $idn]);
} else={
:set $wans ($wans.",".[/ip dhcp-client get value-name=interface $idn]);
}
}
}
# search for lte connections
:foreach idn in=[/interface find where type="lte" and disabled=no] do={
if ([:typeof $wans]="nothing") do={
:set $wans ([/interface get value-name=name $idn]);
} else={
:set $wans ($wans.",".[/interface get value-name=name $idn]);
}
}
}
# If no lan interface input detected
:local lans [:tostr $3];
if ([:len $lans]=0) do={
# search for bridges
:foreach idn in=[/interface find where type="bridge" and disabled=no] do={
if ([:typeof $lans]="nothing") do={
:set $lans ([/interface get value-name=name $idn]);
} else={
:set $lans ($lans.",".[/interface get value-name=name $idn]);
}
}
}
:local wanip do={:if ([:len [/ip dhcp-client find where interface=[:tostr $1]]]>0) do={:return [/ip dhcp-client get [find interface=[:tostr $1]] gateway];} else={:return [$1];}}
:local lanip do={ :return [:pick [:tostr [/ip address get [find where interface=[:tostr $1]] value-name=address]] 0 [:find [:tostr [/ip address get [find where interface=[:tostr $1]] value-name=address]] "/"]] }
:local psfw $4;
:if ($todo="add") do={
foreach wan in=[:toarray $wans] do={
:local wid [:pick [:tostr [/interface find name=$wan]] 1 ([:len [:tostr [/interface find name=$wan]]])];
foreach lan in=[:toarray $lans] do={
# redirect outgoing traffic in local network to wan(s)
:if ([:len [/ip firewall nat find where out-interface=$wan and action=masquerade]]=0) do={
/ip firewall nat add chain=srcnat out-interface=$wan action=masquerade comment="enable internet access via '$wan'"
:log info "'$wan' firewall nat masquerade has been created.";
} else={
/ip firewall nat set comment="enable internet access via '$wan'" [find where out-interface=$wan and action=masquerade];
:log warning "'$wan' firewall nat masquerade exists.";
}
# rollback
:local lid [:pick [:tostr [/interface find name=$lan]] 1 ([:len [:tostr [/interface find name=$lan]]])];
:if ([:len [/ip firewall nat find where out-interface=$lan and action=masquerade and comment="rollback_$lid"]]=0) do={
/ip firewall nat add chain=srcnat out-interface=$lan action=masquerade comment="rollback_$lid"
:log info "'$lan' firewall nat masquerade has been created.";
} else={
:log warning "'$lan' firewall nat masquerade exists.";
}
# redirect incoming traffic in wan(s) to the local network
:if ([:typeof $psfw]!="nothing") do={
:foreach pfwn in=[:toarray $psfw] do={
:if ([:len [/ip firewall nat find where chain=dstnat and protocol=tcp and dst-port=$pfwn and in-interface=$wan and action=dst-nat and to-addresses=[$lanip $lan] and to-ports=$pfwn]]=0) do={
/ip firewall nat add chain=dstnat protocol=tcp dst-port=$pfwn in-interface=$wan action=dst-nat to-addresses=[$lanip $lan] to-ports=$pfwn comment="redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan]:$pfwn)"
:log info "firewall nat redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan]:$pfwn) was created.";
} else={
/ip firewall nat set comment="redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan]:$pfwn)" [find where chain=dstnat and protocol=tcp and dst-port=$pfwn and in-interface=$wan and action=dst-nat and to-addresses=[$lanip $lan] and to-ports=$pfwn]
:log warning "firewall nat \"redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan]:$pfwn)\" exists.";
}
}
} else={
:if ([:len [/ip firewall nat find where chain=dstnat and in-interface=$wan and action=dst-nat and to-addresses=[$lanip $lan]]]=0) do={
/ip firewall nat add chain=dstnat in-interface=$wan action=dst-nat to-addresses=[$lanip $lan] comment="redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan])"
:log info "firewall nat \"redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan])\" was created.";
} else={
/ip firewall nat set comment="redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan])" [find where chain=dstnat and in-interface=$wan and action=dst-nat and to-addresses=[$lanip $lan]]
:log warning "firewall nat \"redirect incoming traffic from '$wan' to '$lan' ($[$lanip $lan])\" exists.";
}
}
# what comes from specific wan, gets out from specific same wan
:if ([:len [/ip firewall mangle find where action=mark-connection and chain=input and in-interface=$wan and new-connection-mark="conn_$wid"]]=0) do={
/ip firewall mangle add action=mark-connection chain=input in-interface=$wan new-connection-mark="conn_$wid" dst-address-type=!local passthrough=yes comment="incoming from '$wan' outgoing to '$wan'"
:log info "firewall mangle \"incoming from '$wan' outgoing to '$wan'\" was created.";
} else={
/ip firewall mangle set dst-address-type=!local passthrough=yes comment="incoming from '$wan' outgoing to '$wan'" [find where action=mark-connection and chain=input and in-interface=$wan and new-connection-mark="conn_$wid"]
:log warning "firewall mangle \"incoming from '$wan' outgoing to '$wan'\" exists.";
}
:if ([:len [/ip firewall mangle find where action=mark-routing and chain=output and connection-mark="conn_$wid" and new-routing-mark="traffic_$wid"]]=0) do={
/ip firewall mangle add action=mark-routing chain=output connection-mark="conn_$wid" new-routing-mark="traffic_$wid" passthrough=no comment="outgoing to '$wan' incoming from '$wan'"
:log info "firewall mangle \"outgoing to '$wan' incoming from '$wan'\" was created.";
} else={
/ip firewall mangle set passthrough=no comment="outgoing to '$wan' incoming from '$wan'" [find where action=mark-routing and chain=output and connection-mark="conn_$wid" and new-routing-mark="traffic_$wid"];
:log warning "firewall mangle \"outgoing to '$wan' incoming from '$wan'\" exists.";
}
# forwards from specific wan, gets out from specific same wan
:if ([:len [/ip firewall mangle find where action=mark-connection and chain=forward and in-interface=$wan and new-connection-mark="pfw_$wid"]]=0) do={
/ip firewall mangle add action=mark-connection chain=forward in-interface=$wan connection-state=new new-connection-mark="pfw_$wid" passthrough=no comment="forwards incoming from '$wan' outgoing to '$wan'"
:log info "firewall mangle \"forwards incoming from '$wan' outgoing to '$wan'\" was created.";
} else={
/ip firewall mangle set connection-state=new passthrough=no comment="forwards incoming from '$wan' outgoing to '$wan'" [find where action=mark-connection and chain=forward and in-interface=$wan and new-connection-mark="pfw_$wid"]
:log warning "firewall mangle \"forwards incoming from '$wan' outgoing to '$wan'\" exists.";
}
:if ([:len [/ip firewall mangle find where chain=prerouting and in-interface=$lan and connection-mark="conn_$wid" and action=mark-routing and new-routing-mark="traffic_$wid"]]=0) do={
/ip firewall mangle add chain=prerouting in-interface=$lan connection-mark="conn_$wid" action=mark-routing new-routing-mark="traffic_$wid" comment="prerouting incoming from '$lan' outgoing to '$wan'"
:log info "firewall mangle \"prerouting incoming from '$lan' outgoing to '$wan'\" was created.";
} else={
/ip firewall mangle set comment="prerouting incoming from '$lan' outgoing to '$wan'" [find where chain=prerouting and in-interface=$lan and connection-mark="conn_$wid" and action=mark-routing and new-routing-mark="traffic_$wid"];
:log warning "firewall mangle \"prerouting incoming from '$lan' outgoing to '$wan'\" exists.";
}
if ([:len [/ip firewall mangle find where chain=prerouting and in-interface=$wan and action=mark-connection and new-connection-mark="conn_$wid"]]=0) do={
/ip firewall mangle add chain=prerouting in-interface=$wan action=mark-connection new-connection-mark="conn_$wid" comment="prerouting incoming from '$wan' outgoing to '$lan'"
:log info "firewall mangle \"prerouting incoming from '$wan' outgoing to '$lan'\" was created.";
} else={
/ip firewall mangle set comment="prerouting incoming from '$wan' outgoing to '$lan'" [find where chain=prerouting and in-interface=$wan and action=mark-connection and new-connection-mark="conn_$wid"]
:log warning "firewall mangle \"prerouting incoming from '$wan' outgoing to '$lan'\" exists.";
}
# routing rules for wans' traffic
:if ([:len [/ip route find where dst-address=0.0.0.0/0 and gateway=[$wanip $wan] and distance=1 and routing-mark="traffic_$wid"]]=0) do={
/ip route add dst-address=0.0.0.0/0 gateway=[$wanip $wan] distance=1 routing-mark="traffic_$wid" comment="routing rules for '$wan' traffic"
:log info "firewall mangle \"routing rules for '$wan' traffic\" was created.";
} else={
/ip route set comment="routing rules for '$wan' traffic" [find where dst-address=0.0.0.0/0 and gateway=[$wanip $wan] and distance=1 and routing-mark="traffic_$wid"];
:log warning "firewall mangle \"routing rules for '$wan' traffic\" exists.";
}
}
}
:set $i ($i+1);
}
:if ($todo="remove") do={
foreach wan in=[:toarray $wans] do={
:local wid [:pick [:tostr [/interface find name=$wan]] 1 ([:len [:tostr [/interface find name=$wan]]])];
foreach lan in=[:toarray $lans] do={
# redirect incoming traffic in wan(s) to the local server
/ip firewall nat remove [find where chain=dstnat and protocol=tcp and dst-port=$pfwn and in-interface=$wan and action=dst-nat and to-addresses=[$lanip $lan] and to-ports=$pfwn]
/ip firewall nat remove [find where chain=dstnat and in-interface=$wan and action=dst-nat and to-addresses=[$lanip $lan]]
# rollback
:local lid [:pick [:tostr [/interface find name=$lan]] 1 ([:len [:tostr [/interface find name=$lan]]])];
/ip firewall nat remove [find where out-interface=$lan and action=masquerade and comment="rollback_$lid"];
# what comes from specific wan, gets out from specific same wan
/ip firewall mangle remove [find where action=mark-connection and chain=input and in-interface=$wan and new-connection-mark="conn_$wid"]
/ip firewall mangle remove [find where action=mark-routing and chain=output and connection-mark="conn_$wid" and new-routing-mark="traffic_$wid"]
# port forwards from specific wan, gets out from specific same wan
/ip firewall mangle remove [find where action=mark-connection and chain=forward and in-interface=$wan and new-connection-mark="pfw_$wid"]
/ip firewall mangle remove [find where action=mark-routing and chain=prerouting and in-interface=$lan and connection-mark="pfw_$wid" and new-routing-mark="traffic_$wid"]
/ip firewall mangle remove [find where chain=prerouting and in-interface=$lan and connection-mark="conn_$wid" and action=mark-routing and new-routing-mark="traffic_$wid"]
/ip firewall mangle remove [find where chain=prerouting and in-interface=$wan and action=mark-connection and new-connection-mark="conn_$wid"]
# routing rules for wans' traffic
/ip route remove [find where dst-address=0.0.0.0/0 and gateway=[$wanip $wan] and distance=1 and routing-mark="traffic_$wid"]
}
}
}
}