View network interfaces and change (spoof) MAC address in Linux

This is a basic Linux networking task and can be done via command line and graphical interface. The NetworkManager software is used to create and view network connections with graphical interface, which may look different depending on the desktop environment. Because the NetworkManager is easy to use and has a lot of front ends, this tutorial will cover only the command line method, we will use the ip and ifconfig commands, it’s recommended to use the ip command because ifconfig is obsolete, so open your favorite terminal emulator and let’s start!

Display network devices, state, MAC address, IP address, network class and statistics

As you see I have three interfaces, “lo” is the loopback interface, “eth0” the wired network card and “wlan0” the wireless card, I am using the classic naming scheme.

ip -s addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
    RX: bytes  packets  errors  dropped overrun mcast 
    2640       44       0       0       0       0        
    TX: bytes  packets  errors  dropped carrier collsns 
    2640       44       0       0       0       0            
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:00:00:00:00:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.2/24 brd 192.168.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5ef3:fcff:feec:f454/64 scope link 
       valid_lft forever preferred_lft forever
    RX: bytes  packets  errors  dropped overrun mcast 
    149454253  137261   0       0       0       40      
    TX: bytes  packets  errors  dropped carrier collsns 
    16640485   92276    0       0       0       0       
12: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 00:00:00:00:00:02 brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast 
    0          0        0       0       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    0          0        0       0       0       0       

Legend: Interface, State, MAC Address, IP Address, Network Class, Statistics

Or with the obsolete ifconfig

ifconfig -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.2  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::5ef3:fcff:feec:f454  prefixlen 64  scopeid 0x20
        ether 00:00:00:00:00:01  txqueuelen 1000  (Ethernet)
        RX packets 59133  bytes 35479715 (33.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 46498  bytes 9805836 (9.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 16  memory 0xf7ca0000-f7cc0000  

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10
        loop  txqueuelen 1  (Local Loopback)
        RX packets 124  bytes 7440 (7.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 124  bytes 7440 (7.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 00:00:00:00:00:02  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Legend: Interface, State, MAC Address, IP Address, Network Class, Statistics

Displaying the routing table, 192.168.0.1 is my default gateway

ip route
default via 192.168.0.1 dev eth0

Or with the obsolete route and netstat commands

route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.1     0.0.0.0         UG    0      0        0 eth0
netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.0.1     0.0.0.0         UG        0 0          0 eth0

Displaying DNS servers

cat /etc/resolv.conf
nameserver 192.168.0.1

Change (spoof) the MAC address

ip link set dev eth0 down
ip link set dev eth0 address 11:11:11:11:11:11
ip link set dev eth0 up

Or with the obsolete ifconfig

ifconfig eth0 down
ip link set dev eth0 address 11:11:11:11:11:11
ifconfig eth0 up

The modification with ip and ifconfig are not reboot proof, in order to make the change reboot proof you can use NetworkManager

nmcli connection modify eth0 ethernet.cloned-mac-address 11:11:11:11:11:11
nmcli connection up eth0

Create Linux and Unix bootable USB flash drive in Linux with command line

In this tutorial we will create a Linux bootable USB drive in Linux via command line with two methods, in the first method we will use the dd command, a byte by byte copying tool available on Unix-like operating systems. In the second method, we will create it manually. Root permission is required.

Test environment: Debian 9.3 with mkfs.vfat 4.1
Test files: Debian 9.3 (ISOHybrid, Method 1) and KNOPPIX 7.7 (ISO9660, Method 2)

First, identify the USB drive, in my example the device is /dev/sdx (Kingston DT microDuo 3.0 16G).
Warning: All the data on the USB drive will be destroyed without warning! Make sure you selected the correct drive or you will destroy a wrong disk!

lsblk -S
NAME HCTL       TYPE VENDOR   MODEL             REV TRAN
sda  0:0:0:0    disk ATA      Samsung SSD 850  1B6Q sata
sdx  6:0:0:0    disk Kingston DT microDuo 3.0  PMAP usb
fdisk -l /dev/sdx
Disk /dev/sdx: 14.4 GiB, 15502147584 bytes, 30277632 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x28853db5

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdx1  *     2048 30277631 30275584 14.4G  c W95 FAT32 (LBA)

Method 1 – using dd (Data Duplicator)

The dd command will create an exact copy of the ISO file, the content will be copied byte by byte onto the USB drive. The file must be an ISOHybrid image and obviously must be smaller than the USB drive’s capacity.

The big advantage of using this method is that it’s fast and easy, you don’t need to worry about partitioning, formatting and installing the bootloader, but there are disadvantages too.

With this method you won’t be able to use the entire capacity of the USB drive and operating systems like Microsoft Windows or macOS will not recognize it. The third disadvantage is that you cannot add or modify files even if you manage to access the content, because you won’t have enough free space or the file system is read only (see ISO9660).

Most of the Linux distributions uses ISOHybrid images while Unix BSD operating systems offers you separate image files (FreeBSD *memstick.img or OpenBSD install*.fs).

1. Check if the file is an ISOHybrid image, it must contain an MBR while the ISO9660 doesn’t. You can use the file command or hexdump the first 512 bytes.

a.) As you see the file command does not detect the MBR or hexdump shows just zeros, if you write this image it will not boot, it’s an ISO9660 image.

file KNOPPIX_V7.7.1DVD-2016-10-22-EN.iso
KNOPPIX_V7.7.1DVD-2016-10-22-EN.iso: ISO 9660 CD-ROM filesystem data 'KNOPPIX' (bootable)
hexdump -n 512 KNOPPIX_V7.7.1DVD-2016-10-22-EN.iso
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
0000200

b.) The file command detected the MBR, this is what we need to use the dd command, it’s an ISOHybrid image.

file debian-9.3.0-amd64-xfce-CD-1.iso
debian-9.3.0-amd64-xfce-CD-1.iso: DOS/MBR boot sector; partition 2 : ID=0xef, start-CHS (0x3ff,254,63), end-CHS (0x3ff,254,63), startsector 7348, 832 sectors
hexdump -n 512 debian-9.3.0-amd64-xfce-CD-1.iso
...
00001b0 1ff4 0000 0000 0000 7fe7 5398 0000 0080
00001c0 0001 3f00 86a0 0000 0000 3800 0014 fe00
00001d0 ffff feef ffff 1cb4 0000 0340 0000 0000
00001e0 0000 0000 0000 0000 0000 0000 0000 0000
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200

2. Write the ISOHybrid image to the USB drive. All data on /dev/sdx will be destroyed!

dd if=debian-9.3.0-amd64-xfce-CD-1.iso of=/dev/sdx bs=5M status=progress
587202560 bytes (587 MB, 560 MiB) copied, 5.02833 s, 117 MB/s
129+1 records in
129+1 records out
678428672 bytes (678 MB, 647 MiB) copied, 69.5308 s, 9.8 MB/s

Method 2 – manually (MBR partitioning scheme)

Install requirements:

apt-get install dosfstools
apt-get build-dep syslinux

1. Delete partitions by clearing the Master Boot Record, the following command will write 0x00 to the first 512 bytes. All data on /dev/sdx will be destroyed!

dd if=/dev/zero of=/dev/sdx bs=512 count=1
1+0 records in
1+0 records out
512 bytes copied, 0.00290024 s, 177 kB/s

2. Create one big partition with boot flag on.

echo ',,c;*' | sfdisk /dev/sdx
New situation:
Device     Boot Start      End  Sectors  Size Id Type
/dev/sdx1  *     2048 30277631 30275584 14.4G  c W95 FAT32 (LBA)

The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

3. Format the created partition /dev/sdx1 as FAT32 with the label “LINUX”.

mkfs.vfat -F32 /dev/sdx1 -n "LINUX"
mkfs.fat 4.1 (2017-01-24)

4. Mount the Linux ISO image for this example we will use KNOPPIX.

mkdir /mnt/iso
mount KNOPPIX_V7.7.1DVD-2016-10-22-EN.iso /mnt/iso

5. Search for isolinux.bin and check the version, download the same syslinux version and extract the archive.

find /mnt/iso -name "isolinux.bin" | xargs strings | grep -i isolinux
ISOLINUX 6.03 20171018
isolinux:
wget https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.gz
tar -zxvf syslinux-6.03.tar.gz

6. Write the bootstrap code (mbr.bin) to the MBR of /dev/sdx. In syslinux version 6 the file path is bios/mbr/mbr.bin while in version 4 and 5 is mbr/mbr.bin.

dd if=syslinux-6.03/bios/mbr/mbr.bin of=/dev/sdx bs=440 count=1

7. Install syslinux, this will alter the boot sector and copy ldlinux.sys into the root directory. In syslinux version 6 the file path is bios/linux/syslinux while in version 4 and 5 is linux/syslinux.

syslinux-6.03/bios/linux/syslinux -i /dev/sdx1

8. Mount the USB drive and create syslinux.cfg.

mkdir /mnt/usb
mount /dev/sdx1 /mnt/usb/
echo -e "DEFAULT boot\nLABEL boot\n" > /mnt/usb/syslinux.cfg
find /mnt/iso/ -name isolinux.cfg | awk -F "/mnt/iso|isolinux.cfg" '{print "CONFIG " $2 "isolinux.cfg\nAPPEND " $2}' >> /mnt/usb/syslinux.cfg

9. Copy the Linux installation files to the USB drive, it might take a few minutes.

cp -rTv /mnt/iso/ /mnt/usb/

10. Unmount the USB drive. Don’t skip this step! Is needed to complete all pending writes.

umount /dev/sdx1

Finally

It should work on most of Linux distros, but there are exceptions.
Fedora and CentOS will mount the file system by LABEL, for example in CentOS 7 the LABEL must be CentOS\x207\x20x86_64. Bad for us because FAT32 supports a maximum of 11 characters, you must change the LABEL in isolinux.cfg and grub.cfg in multiple places.

/mnt/usb/isolinux/isolinux.cfg

..
  append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet
..

/mnt/usb/EFI/BOOT/grub.cfg

..
search --no-floppy --set=root -l 'CentOS 7 x86_64'

### BEGIN /etc/grub.d/10_linux ###
menuentry 'Install CentOS 7' --class fedora --class gnu-linux --class gnu --class os {
	linuxefi /images/pxeboot/vmlinuz inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet
	initrdefi /images/pxeboot/initrd.img
}
..