RouterOS change MAC in rand automatically .

因為有一些需求, 有一台 RouterBoard 得一直換 MAC address . 花了一點時間研究了一下 RouterOS script , 讓指定的 interface 換上 rand 的mac address .  從網路上找到現成的 code 可以產生出 rand mac address , 但真要拿來用, 卻有不小的機率出現 failure: invalid mac address … 研究了一下  mac address 的規則, 看不出啥端倪, 索性就修改了下這個現成的 code , 並弄成一個 function , 可以自己一直試到成功為止. 同時也設下了一個重試的上限 . 紀錄如下, 也歡迎有需求的人直接享用 .



:global gainmac 
:global lastmac 0
:global funGainMac do={
    # modified from https://forum.mikrotik.com/viewtopic.php?t=91229
    # Generate random-ish MAC address
    # Tested on RouterOS v6.49.7 
    
    #to call global function , need to declare in function . 
    :global funGainMac
    :global gainmac 
    :global lastmac 


    # if firewall rules can't be found, add them
    if ( [ :len [ /ip firewall filter find comment~"fwrnum" ] ] = 0 ) do={
        :for i from=1 to=12 do={
            /ip firewall filter add action=passthrough chain=input random="$i" comment="fwrnum$i";
        }
    }

    #delay 1500ms to wait for the rand rule above be ready
    :delay 700ms

    # MAC characters array
    :local macTable A,B,C,D,E,F,0,1,2,3,4,5,6,7,8,9
    # length of MacTable array
    :local macTableLen [ :len $macTable ];
    # variable that will hold our mac address
    :local mac;

    # generate 12 mac address characters
    :for i from=1 to=12 do={
    # get packet number from each firewall rule
        :local v [/ip firewall filter get [find comment="fwrnum$i"] packets ];
    # add $i*$i value to $v
        :set v ( $v + ( $i * $i ) );
    # add time values, last value of minutes, and both seconds values
        :local t ( [ :pick [/system clock get time] 4 5 ] . [ :pick [/system clock get time] 6 8 ] );
    # reverse values, increasing frequency of first number change
        :set t ( [ :pick $t 2 ] . [ :pick $t 1 ] . [ :pick $t 0 ] );
    # add time seed to $v
        :set v ( $v + $t );
    # if packet number is greater than 100, just grab last 2 digits, as they change most frequently
        if ( $v >= 100 ) do={
            :set v [ :pick $v ( [ :len $v ] - 2 ) [ :len $v ] ];
        }
    # reverse the two digits, increasing frequency of variable change
        :set v ( [ :pick $v 1 ] . [ :pick $v 0 ] );
    # while the value is greater than or equal to the length of the macTable array
        while ( $v >= $macTableLen ) do={
    # subtract 15, one less than macTable length, so as to create a rainbow effect so to speak
            :set v ( $v - 15 );
        }
    # create mac starting at the end, get mac char from macTable based on our value
        :set mac ( [ :pick $macTable $v ] . $mac );
    # add mac address colons at appropriate spots
        if ($i = 2 || $i = 4 || $i = 6 || $i = 8 || $i = 10) do={
            :set mac ( ":" . $mac );
        }
    }

    # remove firewall rules
    /ip firewall filter remove [ find comment~"fwrnum" ];
    :local fNotToChang 0

    if ( $mac = $lastmac) do={
        $funGainMac
        :set fNotToChang 1
    }

    if ( $fNotToChang = 0 ) do={
        :set gainmac $mac
        :set lastmac $mac
    }


}

:global funSetMac do={

    :global funGainMac
    :global funSetMac
    :global gainmac 
    :local mac

    $funGainMac
    :set mac $gainmac

    # show mac address
    #:put $mac;
    #:put [/interface ethernet set ether5-slave-local mac-address=$mac];
    #[/interface ethernet set $strEth mac-address=$mac];
    :do {
        [/interface ethernet set $strEth mac-address=$mac];
    } on-error={};

    :local newmac [/interface ethernet get [find where name="$strEth"] mac-address];
    #:put $newmac;
    :local strMsg 
    if ($mac = $newmac) do={
        #:put "$strEth change MAC ok !!";
        :set strMsg ", $strEth change MAC ok !!"
    } 

    :local b $1;
    :set b ($1-1);
    :put "$b, mac=$mac, mac of Eth = $newmac $strMsg" ;
    if ($b > 0 and $mac != $newmac ) do={                
        $funSetMac strEth=$strEth $b
    }


}

:global funSetMacBridge do={

    :global funGainMac
    :global funSetMacBridge
    :global gainmac 
    :local mac

    $funGainMac
    :set mac $gainmac

    # show mac address
    #:put $mac;
    :do {
        [/interface bridge set $strEth auto-mac=yes];
        [/interface bridge set $strEth auto-mac=no];
        [/interface bridge set $strEth auto-mac=no admin-mac=$mac ];
    } on-error={};

    :local newmac [/interface bridge get [find where name="$strEth"] admin-mac];
    #:put $newmac;
    :local strMsg 
    if ($mac = $newmac) do={
        #:put "$strEth change MAC ok !!";
        :set strMsg ", $strEth change MAC ok !!"
    } 

    :local b $1;
    :set b ($1-1);
    :put "$b, mac=$mac, mac of Eth = $newmac $strMsg" ;
    if ($b > 0 and $mac != $newmac ) do={                
        $funSetMacBridge strEth=$strEth $b
    }


}

#call funSetMac , arg0=define interface name , arg1= times to retry
$funSetMacBridge strEth="bridge" 15
:put "-----------------------";
$funSetMac strEth="ether5" 15
:put "-----------------------";
$funSetMac strEth="ether4" 15
:put "-----------------------";
$funSetMac strEth="ether3" 15
:put "-----------------------";
$funSetMac strEth="ether2" 15
:put "-----------------------";


 

Share your vote!


Do you like this post?
  • Fascinated
  • Happy
  • Sad
  • Angry
  • Bored
  • Afraid

Leave a Reply

Your email address will not be published. Required fields are marked *


Please help to input verification code