Setting TAP interface MAC address without NET_ADMIN capabilities
When working with TAP interfaces, you might need to change MAC addresses without having NET_ADMIN capabilities. This post explores an alternative approach using the same method that DPDK employs.
The Standard Approach and Its Limitations
Changing the MAC address of an interface normally requires net_admin capabilities. Let's take the ip link
command
for example:
1 2 3 4 5 |
|
The reason for this is that ip link
uses netlink to achieve the MAC address change:
1 2 3 4 5 6 7 8 9 |
|
And the netlink kernel code checks for net_admin capabilities.
https://github.com/torvalds/linux/blob/bc9ff192a6c940d9a26e21a0a82f2667067aaf5f/net/netlink/af_netlink.c#L906
1 2 3 4 5 |
|
The Alternative: Using SIOCSIFHWADDR
There's actually another way to set the MAC address on Linux for TAP interfaces, via the SIOCSIFHWADDR ioctl call. This is the same approach that DPDK uses for TAP interface manipulation.
The key is that we can open the TAP interface through /dev/net/tun
and use the SIOCSIFHWADDR ioctl directly, bypassing the netlink interface that requires NET_ADMIN capabilities.
The reason this works is that for most interfaces, the Linux kernel actually checks for CAP_NET_ADMIN when using SIOCSIFHWADDR: https://github.com/torvalds/linux/blob/40f92e79b0aabbf3575e371f9054657a421a3e79/net/core/dev_ioctl.c#L804
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
However, for TAP interfaces, the same check for capabilities is not implemented.
Writing the tool
Let's examine this approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
|
Building and Using the Tool
Compile the program:
1 |
|
Now you can change the MAC address without requiring NET_ADMIN capabilities:
1 2 3 4 5 6 7 8 |
|