In my earlier post on getting a Ubuntu VM running on VPC, I neglected one important and usually insignificant detail: how to disable udev for the VM’s NICs.

The problem with udev is that it effectively disables the VM’s NIC under certain conditions. To understand why, it helps to make some observations about the various modules involved.

Udev is the device manager for Linux 2.6 systems. It is responsible for populating /dev with only the devices that are present. It provides notification to other software when devices are changed. And, most importantly for this blog post, it provides “persistent naming for devices when they move around the device tree.” So, if you move your USB cabling and routers around, your machine should still be able to identify, say, your printer. Or if you add a new NIC and your system detects it before your existing eth0, your old NIC will still be eth0 and your new one will be eth1. This is pretty awesome, and it helps resolve some of the problems I remember having with old PCs, trying to guess which device name maps to which physical device.

On Hyper-V (or Virtual Server, or Virtual PC), NICs are usually virtual, so they get assigned virtual MAC addresses. The default configuration is to let Windows pick the MAC address. These MAC addresses are typically stable, unless you do something like recreate the NIC or move the VM to a new host.

The scenario that this blog post is concerned about is this: you set up a VM on one host, and then you move it to another host. You might move it for any number of reasons: you set it up on VPC and want to permanently host it on Hyper-V, or your Hyper-V hosting situation changes and you need to migrate VMs around, or whatever. Following the move, your VM is no longer on the network! Bad news.

So, when you’re setting up your VM, you need to consider how udev will interact with Hyper-V. Some possible solutions include assigning a static MAC address to the NIC, or making udev smart enough to realize that if the old NIC went away and a new one is in its place, that it should use the new one in place of the old one. My solution is to make udev ignore eth*, since I usually am configuring a Linux VM to run some particular service, and I will not be changing the network configuration in any significant way. My solution is likely to be affected by upgrades because it modifies files that are generated by scripts.

And now, to the point of this post: how to make udev ignore your eth* devices:

  1. Open /etc/udev/rules.d/75-persistent-net-generator.rules in your favorite text editor.
  2. On line 21, where it says KERNEL!="eth*|ath*… remove eth*|. For example, on my system, I start with
    KERNEL!="eth*|ath*|wlan*[0-9]|ra*|sta*|ctc*|lcs*|hsi*", GOTO="persistent_net_generator_end"
    and end up with
    KERNEL!="ath*|wlan*[0-9]|ra*|sta*|ctc*|lcs*|hsi*", GOTO="persistent_net_generator_end"
  3. If udev has already renamed your nic, you’ll also need to open /etc/udev/rules.d/70-persistent-net.rules and remove any eth* entries you find.

This should work on any Linux with udev (kernel >= 2.6). Line 21 is the right one to change on Ubuntu 8.10 and 8.04.2 systems that I’ve configured this way.


UPDATE: I discovered a ubuntu package called “likewise-open” that handles the AD integration very easily.

At work, we run a mostly Windows network — most people spend their day logged into a workstation on our Windows domain.

We have some random unix servers around, and people with accounts on said servers have to maintain credentials in as many places as they have unix accounts. Being on the network team, I have access to many unix machines, such as firewalls, dev boxes, production servers, etc. A couple years ago, I wrote a script to help me change my password, so that when I changed my password, I’d be able to change it everywhere. Currently, there are 12 machines that the script logs into for me. One advantage of this system is that I get a lot of practice typing new passwords, and haven’t ever forgotten the new password. Among the obvious disadvantages of this arrangement is that it’s easy for a change to go unnoticed, which leaves stale passwords in new machines and makes me have to wait for network timeouts when old machines get turned off.

So, enter a new virtual unix machine I’m setting up. I’d really like to integrate it with ActiveDirectory. It’s really time for SSO. It’s way past time, in fact.

My distro of choice is ubuntu. The latest release available is 8.10 (beta). In the rest of this post, I’ll cover getting Ubuntu installed in a virtual machine in Microsoft’s Virtual PC, and how to get said virtual machine onto the domain.

Step 1 is installing Ubuntu into a VM. This is already documented by corey-m in a post titled “Installing Ubuntu Server 8.04 Hardy in Microsoft Virtual PC 2007.” The only thing I did differently was, towards the end, to edit the grub configuration while I was in the recovery console. This removed the need to change boot params during boot.

NOTE: If you install on Hyper-V, you don’t need “noreplace-paravirt”, and, in fact, that option seems to slow the VM down quite a bit.

Step 2 is hooking into AD. For this, I started with a HOWTO on using Winbind to authenticate to Active Directory, from ubuntu’s community wiki. I deviated a bit from the steps listed, so I’ll include the full details here. I am definitely not an expert on the intricacies of samba or AD, so some of this may be cargo cult cruft; apologies if I make you do a bunch of pointless stuff.

The basic steps will be:

  • Install and configure KRB5.
  • Install and configure Samba.
  • Configure PAM.
  • Configure sudo.

Install KRB5

Ensure that /etc/hostname and /etc/hosts (and DNS, if applicable) agree on what your hostname is. hostname –fqd should show the same thing.

sudo apt-get install krb5-user libpam-krb5 krb5-config libkadm55

You’ll be prompted for the kerberos server names. Use your domain controllers’ names.

After installing, I edited /etc/krb5.conf and removed all the extra domains and added DNS mappings in the [domain_realm] section for my domain.

To test, do kinit <username>. You’ll be prompted for your password. Assuming it succeeds, klist will show a ticket. If it fails and says “Client not found in Kerberos database while getting initial credentials”, then kerberos couldn’t find your username. If it says, “Preauthentication failed while getting initial credentials”, then your password is wrong.

Install and configure Samba

sudo apt-get install winbind samba

Replace /etc/samba/smb.conf with this, customized for your network:

  workgroup = MYDOMAIN
  netbios name = MYMACHINE

  winbind refresh tickets = yes
  idmap domains = MYDOMAIN
  idmap config MYDOMAIN:backend = rid
  idmap config MYDOMAIN:range   = 10000-99999

  winbind enum users = yes
  winbind enum groups = yes

  template homedir = /home/%D/%U
  template shell = /bin/bash

  security = ads
  encrypt passwords = yes

Note the lack of spaces around the idmap range. The version of samba in 8.10beta fails to parse the range if there are spaces (e.g. “1000 – 2000”).

One of the things that is different from the HOWTO is the idmap configuration. The default idmap implementation does a simple mapping of SIDs to unix IDs… the first user that logs in will be 10000, the second 10001, etc. If the users log into another server in a different order, they’ll get different user ids. The rid backend provides a deterministic mapping, so it’s only important that the ranges are the same on each unix server. There is an ad backend that uses IDs stored in ActiveDirectory by SFU, if you’ve got that installed.

After modifying smb.conf, restart samba and winbind.

sudo /etc/init.d/winbind stop
sudo /etc/init.d/samba restart
sudo /etc/init.d/winbind start

Join the domain.

sudo net ads join -U <AD account>

Restart samba again. Run wbinfo -u, and you should see a list of users from Active Directory. If not, something is broken.

Configure PAM

Edit /etc/nsswitch.conf and change the lines that look like this

passwd: compat
group: compat

to look like this

passwd: compat winbind
group: compat winbind

Now run sudo getent passwd and you should see the normal /etc/passwd entries, followed by passwd entries for the domain users.

On Ubuntu 8.10, there’s a new auto-configuration tool for PAM, pam-auth-update. If you don’t have pam-auth-update, you should probably just modify your pam configuration as per the HOWTO, rather than using the following configuration for PAM.

If you’re using the new PAM, create the file /usr/share/pam-configs/winbind with the following contents:

Name: Active Directory via Winbind
Default: yes
Priority: 500
Auth-Type: Primary
        [success=end default=ignore] krb5_auth krb5_ccache_type=FILE try_first_pass
        [success=end default=ignore] krb5_auth krb5_ccache_type=FILE
Account-Type: Primary
        [success=end default=ignore]
Session-Type: Additional
        required umask=0022 skel=/etc/skel

The krb5_auth options aren’t required, so leave them off if you have no use for kerberos.

Now run sudo pam-auth-update to push the configuration to /etc/pam.d. Test that you can log in as a domain user (e.g. ssh -l DOMAIN\\user localhost). Test that you can log in as a regular user.

Configure sudo

Presumably, you’ll be basically ignoring your local passwd file from now on, so you’ll want the AD-backed users to be able to use sudo to do admin-ish things.

sudo vi sudoers

Edit appropriately. For example, I added the following line.

%DOMAIN\\Domain\ Admins ALL=(ALL) ALL

Now you’re set up with AD accounts on Ubuntu 8.10. In the future, I’m planning to add a rails application with a SQL Server database behind it, so there may be more in the future for this post.