Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash. Generate random mac address (unicast)

I need to generate in bash random mac addresses without using macchanger or similar.

I have this:

random_mac=$(hexdump -n6 -e '/1 ":%02X"' /dev/random | sed s/^://g)

But with this sometimes, if you try to put the mac into the interace it says SIOCSIFHWADDR: Cannot assign requested address. I investigated about this and it seems something related to unicast addresses. I have a workaround working:

random_mac=00:$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 200 | md5sum | sed -r 's/^(.{10}).*$/\1/;s/([0-9a-f]{2})/\1:/g; s/:$//;')

But I don't like too much this because is not completely random. It has always 00 at the beginning.

Any known bash random mac generator fitting the unicast rule?

I read other methods using od. I'm trying to use as less tools as possible in order to have less requeriments to run the script. Can be done without od? or is od absolutely always included in all Linux distros? If yes, I can use it.

like image 734
OscarAkaElvis Avatar asked Jan 05 '23 09:01

OscarAkaElvis


1 Answers

According to Wikipedia, if the LSB on the first octet is a 0, it's a unicast address. If the 2nd LSB on the first octet is a 1, it's a locally generated MAC address.

0x0     0000
0x1     0001
0x2     0010
0x3     0011
0x4     0100
0x5     0101
0x6     0110
0x7     0111
0x8     1000
0x9     1001
0xA     1010
0xB     1011
0xC     1100
0xD     1101
0xE     1110
0xF     1111

We can see that safe first octets for locally generated MAC addresses are x2, x6, xA, and xE, as they all end in 10. Using awk, we can put those into an array, and then replace the second byte of the output with a random selection.

This updated version will work with either Linux or OS X:

#!/bin/bash
hexdump -n 6 -ve '1/1 "%.2x "' /dev/random | awk -v a="2,6,a,e" -v r="$RANDOM" 'BEGIN{srand(r);}NR==1{split(a,b,",");r=int(rand()*4+1);printf "%s%s:%s:%s:%s:%s:%s\n",substr($1,0,1),b[r],$2,$3,$4,$5,$6}'

Or, spread out a bit:

#!/bin/bash
hexdump -n 6 -ve '1/1 "%.2x "' /dev/random |\
awk -v a="2,6,a,e" -v r="$RANDOM" '
    BEGIN {
        srand(r);
    }
    NR==1 {
        split(a, b, ",");
        r=int(rand() * 4 + 1);
        printf("%s%s:%s:%s:%s:%s:%s\n", substr($1, 0, 1), b[r], $2, $3, $4, $5, $6);
    }
'
like image 91
miken32 Avatar answered Jan 08 '23 06:01

miken32