If you happen to wonder how im changing my MAC on the WAN side pseudo randomly... The scripts are below. These I did NOT write, I got tthem from various places here and elsewhere..
:global prngResult;
:global prngParams;
define char table
:global chArray 0abcdef0123456789abcdef012345abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345
:local strPass "";
#Get Random
:set prngParams "1 99 true";
{/system script run Random} ;
:local ch1num 0;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch2num 0;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch3num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch4num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch5num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch6num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch7num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch8num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch9num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch10num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch11num $prngResult;
#Get Random
:set prngParams "1 99 false";
{/system script run Random} ;
:local ch12num $prngResult;
#Get Random
:set prngParams "1 09 true";
{/system script run Random} ;
generate MAC address
:set strPass ( [:tostr [ :pick $chArray $ch1num ]] . [:tostr [:pick $chArray $ch2num ]] . [:tostr [:pick $chArray ($ch3num+$prngResult) ]] . [:tostr [:pick $chArray ($ch4num*2) ]] . [:tostr [:pick $chArray ($ch5num+16) ]] . [:tostr [:pick $chArray ($ch6num+4) ]] . [:tostr [:pick $chArray ($ch7num+12) ]] . [:tostr [:pick $chArray $ch8num ]] . [:tostr [:pick $chArray $ch9num ]] . [:tostr [:pick $chArray $ch10num ]] . [:tostr [:pick $chArray $ch11num ]] . [:tostr [:pick $chArray $ch12num ]] );
:log info $strPass;
/interface ethernet set ether1 mac-address=$strPass;
led user=yes;
:delay 500ms;
led user=no;
\
The random generator script
Binary Galois LFSR 1/63 bits, periods 0-1..(2^63)-1
based on:
usage: call first time after setting prngParams={low,high,true} for initializing
0 <= Low <= High <= ((2^63)-1)
then keep calling ((high - low) + 1) times with prngParams={low,high,false}
to get the permutated interval one item at a time, in prngResult
when no more numbers are inside the LFSR, prngResult starts to be -1
GLOBALS ---------------------------------------------------------------
debug settings
:global dbgMisc;
params / result prng
:global prngParams;
:global prngResult;
register state
:global prngSeed;
:global prngLFSR;
:global prngSeq;
:global prngMask;
START SCRIPT ----------------------------------------------------
#:set prngParams "1 15 true";
copy params to local scope
:local Low [:tonum [:pick $prngParams 0]];
:local High [:tonum [:pick $prngParams 2 4]];
:local Initialize (!![:pick $prngParams 5 12]);
adjust interval to 0..prngMax
:local prngMax ($High - $Low + 1);
initialization
:if ($Initialize = true) do={
time seed
:local seed1 2;
{
:local time [:tostr [/system clock get time]];
:for i from=0 to=([:len $time] -1) do {
:local char [:pick $time $i ($i+1)];
:if ($char!=":") do={:set seed1 ($seed1 * ([:tonum $char] + 1))};
};
}
firewall counter seed
:local seed2 0
:foreach item in=[/ip firewall filter find bytes>0] do={
:set seed2 ($seed2+[/ip firewall filter get $item bytes]);
};
:foreach item in=[/ip firewall nat find bytes>0] do={
:set seed2 ($seed2+[/ip firewall nat get $item bytes]);
};
:foreach item in=[/ip firewall mangle find bytes>0] do={
:set seed2 ($seed2+[/ip firewall mangle get $item bytes]);
};
uptime seed
:local seed3 2;
{
:local uptime [:tostr [/system resource get uptime]];
:for i from=0 to=([:len $uptime] - 1) do {
:local char [:pick $uptime $i ($i+1)];
:if ($char!=":") do={:set seed3 ($seed3 * ([:tonum $char] + 1))};
};
}
cpu load seed
:local seed4 ([/system resource get cpu-load] * 16);
conntrack seed
:local seed5 "";
{
:local t "";
:local s "";
:local d "";
:foreach connection in=[/ip firewall connection find] do={
:local timeout [:tostr [/ip firewall connection get $connection timeout ]];
:for i from=0 to=([:len $timeout] - 1) do {
:local char [:pick $timeout $i ($i+1)];
:if ($char!=":") do={:set t "$t$char"};
};
:local src [:tostr [/ip firewall connection get $connection src-address ]];
:for i from=0 to=([:len $src] - 1) do {
:local char [:pick $src $i ($i+1)];
:if ([:typeof [:find ":." $char]]="nil") do={:set s "$s$char"};
};
:local dst [:tostr [/ip firewall connection get $connection dst-address ]];
:for i from=0 to=([:len $dst] - 1) do {
:local char [:pick $dst $i ($i+1)];
:if ([:typeof [:find ":." $char]]="nil") do={:set d "$d$char"};
};
};
:set seed5 "$t$s$d";
}
checksum seeds
:local prngPreSeed (($seed1 ^ $seed2 ^ $seed3 ^ $seed4) | 1);
:set prngSeed 0;
:for i from=[:len $seed5] to=0 do={
:local charnum [:tonum [:pick $seed5 $i]];
:set prngSeed ($prngSeed ^ ($prngPreSeed / ($charnum + 1)));
}
:put "prngPreSeed=$prngPreSeed, seed1=$seed1, seed2=$seed2, seed3=$seed3, seed4=$seed4, seed5=$seed5";
:put "prngSeed=$prngSeed";
\
array of arrays with taps for maximal period, indexed by bit width (1..63)
:local tapsfor {
"";
"";
"";
"3,2";
"4,3";
"5,3";
"6,5";
"7,6";
"8,6,5,4";
"9,5";
"10,7";
"11,9";
"12,6,4,1";
"13,4,3,1";
"14,5,3,1";
"15,14";
"16,15,13,4";
"17,14";
"18,11";
"19,6,2,1";
"20,17";
"21,19";
"22,21";
"23,18";
"24,23,22,17";
"25,22";
"26,6,2,1";
"27,5,2,1";
"28,25";
"29,27";
"30,6,4,1";
"31,28";
"32,22,2,1";
"33,20";
"34,27,2,1";
"35,33";
"36,25";
"37,5,4,3,2,1";
"38,6,5,1";
"39,35";
"40,38,21,19";
"41,38";
"42,41,20,19";
"43,42,38,37";
"44,43,18,17";
"45,44,42,41";
"46,45,26,25";
"47,42";
"48,47,21,20";
"49,40";
"50,49,24,23";
"51,50,36,35";
"52,49";
"53,52,38,37";
"54,53,18,17";
"55,31";
"56,55,35,34";
"57,50";
"58,39";
"59,58,38,37";
"60,59";
"61,60,46,45";
"62,61,6,5";
"63,62"
};
determine $prngMax bit width
:local highB $prngMax;
:local bits 0;
:while ($highB > 0) do={
:set highB ($highB >> 1);
:set bits ($bits + 1);
};
:if ($bits < 3) do={ :set bits 3 };
get taps for a $bits wide register
:local taps [:toarray [:tostr [:pick $tapsfor $bits]]];
get feedback function
:set prngMask 0;
:for i from=0 to=([:len $taps]-1) do={
:set prngMask ($prngMask | (1 << ([:tonum [:pick $taps $i]]-1)));
};
init register with the seed
:set prngLFSR $prngSeed;
init seq counter
:set prngSeq 0;
};
if we haven't finalized the sequence
:if ($prngSeq < $prngMax) do={
:do {
shift the register until it's high bit is 1 and then apply the mask
we end up with next seq number
:do {
:set prngLFSR (($prngLFSR >> 1) ^ (-($prngLFSR & 1) & $prngMask));
} while ($prngLFSR > $prngMax);
if our first result is 0 we cheat
:set prngResult ($prngLFSR-1);
:if (($prngSeq=0) && ($prngLFSR=0)) do={
:set prngLFSR ($prngLFSR+1);
};
} while (($prngSeq=0) && ($prngResult=-1));
keep the seq count
:set prngSeq ($prngSeq+1);
move result to the original range
:set prngResult ($prngResult+$Low);
} else={
if we completed the sequence then exit
:set prngResult -1;
};
:put $prngResult;