Community discussions

MikroTik App
 
zivtal
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 57
Joined: Sun Feb 05, 2017 6:22 pm

Set multi WAN In/Out connection

Sun Feb 18, 2018 11:11 am

wanInOut.rsc: This script will create a global command (script environment) called $WanInOut

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).
: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"]
            }
        }
    }
}

Who is online

Users browsing this forum: No registered users and 34 guests