Dominic Cronin's weblog
Spoofing a MAC address in gentoo linux
I spent a few hours this weekend fiddling with networking things at home. One of the things I ran into was that the DHCP server provided by my ISP was behaving erratically. Specifically, it was being very fussy about giving out a new lease. It would give out a lease to a Windows 7 system I was using for testing, but not to my Gentoo server. At some point, having spent the day with this kind of frustration, I was ready to put up with almost any hack to get things running. Someone on the #gentoo IRC channel suggested that spoofing the MAC address that already had a lease might be a solution. Their solution was to do this:
ifconfig eth0 down ifconfig eth0 hw ether 08:07:99:66:12:01 ifconfig eth0 up
Here, you have to imagine that eth0 is the name of the interface, although on my system it isn't any more. (Another thing I learned this weekend was about predictable interface names.) You should also imagine that 08:07:99:66:12:01 is the mac address of the network interface on my Win7 system.
The trouble with this is that it doesn't integrate very well in the standard init scripts that get things going on a Gentoo system. Network interfaces are started by running /etc/init.d/net.eth0 (although that's just a link to another script). The configuration is to be found in /etc/init.d/net where you can add directives that control the way your network interfaces are configured. The most important of these are the ones that begin with "config_". For example, to set up a static IP for eth0, you might say something like:
config_eth0="192.168.0.99 netmask 255.255.255.0 brd 192.168.0.255"
or for DHCP it's much simpler:
config_eth0="dhcp"
So my obvious first try for setting up a spoofed MAC address was something like this:
config_eth0="dhcp hw ether 08:07:99:66:12:01"
but this didn't work at all. Anyway - after a bit of fiddling and more Googling (sorry - I can't remember where I found this) it turned out that there's a specific directive just for this purpose. I tried this
mac_eth0="08:07:99:66:12:01" config_eth0="dhcp"
It works a treat. Note that the order is important, which is obvious once you know it I suppose, but wasn't obvious to me until I'd got it wrong once.
The good news after that was that for an established lease, everything worked rather better.
Getting my VMware server to resolve DNS in a reasonable time.
I have a Windows 2012 server that I run under VMWare. I've probably mentioned this image before, as it's the one I use for my Tridion research. I'm fairly unusual in that I like to have my database server running "on the bare metal" of my laptop rather than in the Windows Server image. It's probably just perversity or masochism or whatever, but that's how I roll. What this means is that I have two network interfaces on the image: one configured as "Host only", which I use for my database connections and other "on the box" stuff, and another running NAT. Sure, you could run a development image completely isolated from the Internet, but it'd be a pain, so I run the NAT interface as well.
All good in theory, but as it turned out, it was a pain anyway, because it was taking 10 seconds to resolve a DNS name. Don't ask me why 10 seconds - presumably it was hitting some timeout and then trying an approach that worked better. Anyway - it was getting annoying. Sure I could flip out of the image to run a browser outside, but nah! Apart from anything else, I hate to be irritated by things I don't understand. I don't mind having things I don't understand, - gee, you'd go crazy! - but if it's an in-your-face irritation, that's another story.
So I poked around a bit. I could run:
[net.dns]::GetHostByName("www.yahoo.com")
in my powershell on the image and it would take 10 seconds. Natively on the laptop - instant response. So I had a quick look in the VMWare network settings. There are some obscure settings on the NAT interface for policies for automatically detecting DNS servers. But hang on - was it attempting to get DNS from the Host only interface, or the NAT one? So what would nslookup tell me:
PS C:\Users\Administrator> nslookup Default Server: UnKnown Address: 192.168.126.1 > www.yahoo.com Server: [192.168.126.1] Address: 192.168.126.1 DNS request timed out. timeout was 2 seconds. DNS request timed out. timeout was 2 seconds. DNS request timed out. timeout was 2 seconds. DNS request timed out. timeout was 2 seconds. *** Request to [192.168.126.1] timed-out > server 192.168.146.2 Default Server: [192.168.146.2] Address: 192.168.146.2 > www.yahoo.com Server: UnKnown Address: 192.168.146.2 Non-authoritative answer: Name: ds-eu-fp3.wa1.b.yahoo.com Addresses: 2a00:1288:f00e:1fe::3000 2a00:1288:f006:1fe::3000 2a00:1288:f006:1fe::3001 2a00:1288:f00e:1fe::3001 87.248.112.181 87.248.122.122 Aliases: www.yahoo.com fd-fp3.wg1.b.yahoo.com ds-fp3.wg1.b.yahoo.com ds-eu-fp3-lfb.wa1.b.yahoo.com
OK - so the first thing that this told me was that the default lookup was on my Host only interface, and that this was failing. When I manually set the server to the one on the NAT interface, boom... the response came back in a split second.
Next problem - how do I get it to default to the one that works (yes - I could also attempt to get the Host only one working properly, but not if it's easy to switch to the other - llfe's too short, and with networking, getting it to stop being irritating is much more achievable than understanding!).
After a bit of Googling I discovered that you Windows brings up the network interfaces in a specified order, and the first one becomes the "primary" interface, which in turn is used as the default for DNS and goodness knows what else. All I needed to do was change the order. I picked up a hint from The Regime and was almost surprised to find that also in Windows Server 2012, you can get to the advanced settings of the network interfaces by hitting and releasing the Alt key. (Who knows about this stuff? Isn't that just disturbing?) A couple of minutes later I was testing it and finding that it worked.
So it's all good. I still don't understand networking, but that's never been a serious itch for me.
Pacman
This is mostly by way of a "note to self". I've recently started working at a customer where connecting my computer to their network is not just allowed, but necessary. Once connected, if I want to use the Internet, I have to go through their filtering proxy - presumably to keep the badness of the Internet from their systems (and yes, they do pay a lot of attention to ensuring the machine is virus-free). Previously, when I worked there for a day or two, setting up the proxy was a minor irritation, but as I'm going to be there rather longer, the idea of reconfiguring my networking twice a day started to look pretty unattractive. My first attempt at solving this had been to have a couple of scripts that set up the proxy by making the relevant registry settings, but unfortunately, Windows doesn't pick these up immediately. Yeah - sure - if I could remember to run the scripts before shutting down it might work, but I'm not that obsessive.Or I could get Windows to pick up the settings by opening the various screens... Internet Options... Connections.... LAN Settings... oh wait... there had to be a better way.
It turns out that there's something called a Proxy Auto-configuration file. If you select "Automatically detect settings", then Windows will try and locate one of these on the network using the Web Proxy Auto-discovery Protocol, however the customer in question doesn't do this. My needs were simple enough, though, so I checked the next box down: the one that says "Use automatic configuration script". All that remained was to create the script.
It turns out that you write such things in JavaScript, and it's simply a matter of writing a function which is named in the PAC standard, and using other functions that are made available. Here's what I ended up with (although I'll probably add refinements):
function FindProxyForURL(url, host) { var customerProxy = "PROXY 10.62.40.42:1234"; if (atCustomer()){ if(dnsDomainIs(host, ".internal.customer.com") || dnsDomainIs(host, "localhost")|| dnsDomainIs(host,".local")){ return "DIRECT"; } else return customerProxy; } else { return "DIRECT"; } } function atCustomer(){ return isResolvable("server.not.on.external.dns"); // or maybe // return isInNet(myIpAddress(), "10.62.0.0", "255.255.0.0"); }
Nothing fancy, but it works. I suspect I'll find a few edge cases where I maybe have to enhance the script or even configure things by hand, but for now I have the satisfaction of knowing I can just turn up, plug in, and start work.