Over Ethernet – yes, the entire frame including its Ethernet header is sent by your operating system, and the OS decides what source MAC address to use.
In fact, virtual machine systems (like VMware or Hyper-V) already use this to connect VMs to your real LAN – you might have multiple VMs attached to a single Ethernet card, and each VM will have its own MAC address independent from the host.
Linux, FreeBSD, Windows even have an option to create 'bridges' linking multiple physical Ethernet interfaces together, working exactly like a real Ethernet switch would (even with VLANs and RSTP).
You can either change the MAC address of the network interface (telling the OS to use the new address for everything it transmits), or use "raw sockets" from an individual program to craft and send whatever you like, bypassing the TCP/IP stack. For the latter, use existing tools like libpcap, Scapy, or Nemesis.
ip link would change the MAC address until next reboot:
# ip link set eth0 down
# ip link set eth0 addr ab:cd:ef:ab:cd:ef
# ip link set eth0 up
Or send individual packets with scapy:
>>> send(Ether(src="ab:cd:ef:ab:cd:ef", dst="ff:ff:ff:ff:ff:ff")/IP(src="126.96.36.199", dst="188.8.131.52")/UDP(dport=9)/b"hello")
Sent 1 packets.
Linux even has a "macvlan" feature to create virtual interfaces with different MACs on the same physical Ethernet card:
# ip link add fred0 link eth0 type macvlan mode private
Wi-Fi is a bit more restrictive – you cannot send individual packets with spoofed source, as APs keep track of all stations that are associated to it, and will (AFAIK) discard packets coming from any MAC address that's not in the "associated stations" list.
(This is from the perspective of a station. APs can do whatever they want – it's part of their job, after all, to send packets on behalf of wired devices.)
However, you can still set a different MAC address on the wireless interface, and use that new address for everything, starting with association/authentication to the AP.
Unlike Ethernet, though, the ability to do so depends on the specific wireless hardware and drivers (e.g. Atheros usually supports this, while some Realtek cards might not). On Linux the same
ip link … commands should work.
That said, there are ways to implement layer-2 bridging with Wi-Fi (e.g. if you need to connect an entire building over a directional radio link).
(Okay, this is a bit off-topic now, but included for completeness.)
It's a little more complicated than Ethernet, since there are separate concepts of original source (host which generated the packet) and transmitter (Wi-Fi radio which transmitted the packet); similarly, receiver (Wi-Fi radio which received the packet) and final destination (host which will read/consume the packet).
For example, if computer A (e.g. a laptop) sends a packet towards computer B over WiFi, it will have such headers:
- from (original source): <address of computer A>
- to (receiving Wi-Fi radio): <address of Wi-Fi router>
- to (final destination): <address of computer B>
Notice how there's only one 'from' address, under the assumption that regular Wi-Fi stations will never send packets on behalf of some other device. This saves 6 bytes per packet.
It's the reverse from AP to station – there are two 'from' addresses, "original sender" and "transmitting AP", but only one 'to' address.
So when you need to bridge two Ethernet networks over Wi-Fi, you need the "WDS" aka "4addr" mode, which causes all four addresses – two sources and two destinations – to be sent along with every Wi-Fi frame. The support for this varies. On Linux you can do this through
Note that WDS/4addr mode must be enabled on both ends.
Some systems – such as VirtualBox, or Ubiquiti airMAX radios (when configured as a station without WDS), or OpenWRT in the same configuration – support MAC address translation: masquerading multiple clients between the station's own MAC address, much like IPv4 NAT but at a lower level. This works without any configuration and might be more efficient; it does however create problems if something like a DHCP server relies on clients' MAC addresses being different.
(This is actually the opposite of what we started with – multiple devices behind one MAC, instead of one device with multiple MACs – so let's stop here.)
I'm not sure about Bluetooth. AFAIK, most adapters will not let you change nor otherwise spoof their MAC address, since it is the only addressing method used by all communications – devices recognize each other by their MAC addresses, and store link keys based on the MAC address... Anyway. Not my area.