Add Linux wireless drivers to Debian Install ISOs


This HowTo shows you the process to find, download, and add linux wireless drivers, network drivers, or other drivers (missing firmware) to a Debian installation ISO, and then remaster it for install from a USB stick.


I recently bought a Lenovo X1 Carbon ultrabook. It’s a slim, lightweight machine with no CD / DVD drive, and a couple of USB ports.  That means I needed to wipe the Windows install that was on there, and install Debian 8. Of course, getting the Debian ISOs was no problem. And creating a bootable USB is easy because they are hybridized. But, I was quickly greeted with a screen that complained it could not find my wifi – i.e., it couldn’t detect my wireless card – because it didn’t have the drivers.

Install or load firmware for missing network drivers on Debian

The problem stems from the way Debian is packaged. They do not include “non-free” drivers in the distribution ISOs. It’s a philosophical choice, and it’s not going to change, so there’s no point in tilting at that windmill.

Normally, you can select the option that says: “Install driers from a USB stick”, but, on an ultrabook, there’s a twist: since you don’t have a CDROM / DVDROM drive, adding those drivers from a secondary USB stick doesn’t work! The anaconda installer does not notice a secondary usb stick has been inserted, and flat does not scan it! So, even though you’ve put the needed drivers on that USB stick, it’s still useless.

The answer is to slipstream (Windows lingo) the drivers into the installation media. Debian offers some relatively simple ways to remaster an installation CD, which will cover in depth here in a moment. First, let’s talk about how to get the drivers in the first place.

Getting Debian Linux Wireless Drivers

In my case, the intel network card caused debian to complain that it was missing iwlwifi-6000g2a-6.ucode. A quick DuckDuckGo search reveals that this is part of the firmware-iwlwifi package in Debian. Specifically, 0.43 or higher.

So, if we scroll to the bottom of that page, we can download the .deb file.

Downloading the Debian Installable ISO

Next, we need to get an ISO that we’ll use to create the installable media from which we’ll install Debian. My preferred choice is to use BitTorrent to download the ISO files. It lessens the load on the servers hosting the ISOs, and helps the community give back to the rest of us by using a peer-to-peer connection. For this tutorial, we’re going to be dealing with the CD image, not the DVD image. So, download the CD image from here.

Setting up our working folder

We need a place to work. So, create the folder /home/youruser/custom, and copy the downloaded ISO there.

Prepare the helper scripts

Now, Debian’s Modify CD page has some technical information about this process, but this article is an attempt to make the instructions a little more palatable. That being said, we are going to be using the helper scripts at the bottom, so, copy / paste those scripts, and put them in the/home/youruser/custom directory as well.

Now, open each one, and do a find / replace to find sudo and replace with nothing (we’re removing the sudo commands because it’s easier to operate as root for the duration of this tutorial).

Become root

Because we need access to “root only” system utilities, su to root for the rest of this tutorial. (Alternatively, you could constantly use sudo for everything, but being root for the duration of this operation is probably easier).

The starting point

Right now, your custom directory should look like this:

Now, run this command:

./diunpk debian-8.2.0-amd64-CD-1.iso src dest

This will unpack the ISO file into a timestamped directory. Rename this directory to “CD” for ease of use, then copy ./dipk into that directory:

The script has created a src and dest directory under the CD directory. “Src” is a readonly version of the ISO image you downloaded, and dest is where we are going to be making changes to add our firmware.

Add the non-free firmware to the image.

Create the a directory named firmware-nonfree using this command:

mkdir ./pool/main/f/firmware-nonfree/

Now, copy our downloaded deb file to this directory:

cp /home/youruser/Downloads/firmware-iwlwifi_0.43_all.deb ./pool/main/f/firmware-nonfree/

Lastly, we need to make a symbolic link from the firmware directory just below the root of the ISO to this file so that that installer can find it during the natural installation process, so change directory to the firmware directory (/home/youruser/custom/dest/firmware), and then create the symbolic link:

cd firmware
ln -s ../pool/main/f/firmware-nonfree/firmware-iwlwifi_0.43_all.deb

Here’s what my whole process looked like:

  1. I used the find command to find existing firmware just to confirm it’s location. As I expected, it was in ./pool/main/f/firmware-free.
  2. I created ./pool/main/f/firmware-nonfree to store the non-free drivers.
  3. I used tab completion (in the red box) to create the correct command to copy the firmware from my Downloads directory to the nonfree directory I just created.
  4. I changed directory to the firmware directory that is just below dest/.
  5. I did a directory listing to ensure I was seeing what I was expecting to see, and to look at the symlink for the existing firmware.
  6. I created a symbolic link to the new, non-free firmware I just added.
  7. I did a directory listing to make sure it was done correctly.

Run dipk to generate the ISO.

Chagnge directories back to CD (the parent directory of dest), and run the following command:

./dipk ../custom.iso src dest

This will create a file called custom.iso in the custom directory  (the parent directory of the CD directory) using the src and dest files that we have been working with.

Preparing the ISO for use with a USB Drive.

In order to use a USB stick to boot this ISO file and install Linux, we need to use the utility isohybrid, so run the follwoing command from the custom directory:

isohybrid custom.iso

This changes the ISO file to allow modern BIOSes to recognize its structure as a bootable disk.

Prepare your USB Stick

Lastly, put your USB stick in the computer, and run dmesg to figure out which device it is. (It’s usually the last /dev/sdX to show up in dmesg). In my case, it was /dev/sdm. Now, just copy the ISO file to that device:

cp custom.iso /dev/sdX

(Note: be sure to replace the “X” with the proper letter that represents your USB drive!).


Setting Up a VPN with Tinc VPN Software

Setting up a VPN can seem like a daunting task. There are some high-priced options out there, but most of those are closed source, and therefore not to be trusted. Instead, the internet has a variety of open source and free VPN server solutions. OpenVPN is a good one, but does not offer a distrbuted style “mesh network”. It requires a dedicated server, which may or may not be in your budget or scope. But, tinc-vpn offers “point to point” VPN as well as server style and everything in between.

As stated on the project homepage , tinc is a Virtual Private Network (VPN) daemon that uses tunnelling and encryption to create a secure private network between hosts on the Internet. It’s is an excellent way to create connections to servers and workstations over the internet. In particular, I came across it while looking for free alternatives to While tinc does not provide any sort of interface, it can be used to solve the problem of “permanent” remote access.

There are not a lot of great tutorials on the internet for tinc. So, we are going to take an in-depth look at exactly how to set-up a “server” and a client.

For starters, let’s build out our network on paper before we attempt to get it working in real life. In order to get around firewalls on remote networks, we have “punch through” by initiating a connection from within those remote networks. Routers assume that connections made by computers on the “inside” of their networks have permission to do so, and let those connections be made. Additionally, those same routers allow the return traffic through the firewall because: “what good is a request of we don’t allow the response back through to the requester?”

Thus, we need a centralized VPN “server” that all our remote nodes can connect to. Once we have that set-up, we can connect other computers (like a management workstation and a remote file server that we need to manage) to the VPN via the central node.

Setting up a VPN: the tinc VPN Basics

Up until now, I have been referring to a “server” for the central node. tinc does not have a “server”mode because all nodes are configured the same. For our purposes, the “server” we are configuring is a regular node that doesn’t connect to anyone else (pro-actively). Instead, it’s the place where “everyone else” connects to the network.

With that piece of information out of the way, let’s get back to the basics.

Order of Operations: How tinc reads configuration files (and in what order).

When tincd is started, the first thing it does is check /etc/tinc/nets.boot. Each line in that configuration file can contain the name of a network to join. For this tutorial, we are just going to use a single network, but you could set-up as many networks for your server as you wanted to.

After reading /etc/tinc/nets.boot, tinc goes to each network folder looking for a tinc.conf file. So, if your nets.boot file has a single entry: myvpn, tincd will look in /etc/tinc/myvpn/ for a tinc.conf file. (It will look for /etc/tinc/myvpn/tinc.conf).

Once it finds the tinc.conf file for this network, it will read it, and access information under the hosts directory for that network. So, if we use the “ConnectTo” directive to tell tincd that it should connect to a given server, it will look in /etc/tinc/myvpn/hosts/ for the value of that directive.

So, for example, if we are configuring a client (node) to ConnectTo a server that we have nicknamed “MainServer”, we’d use a directive like this:


Once tincd sees the value of that ConnectTo directive is “MainServer” it will immediately look in /etc/tinc/myvpn/hosts for the MainServer file. (It will want /etc/tinc/myvpn/hosts/MainServer). Once it finds that file, it will load configuration information about that host (node) from that file.

But, it also looks in the hosts directory to find information about itself! So, to get two computers to connect to one another, you must (at minimum) have two files in the hosts/ directory for your connections. One for the “server” and one for the “client”

But, tinc also uses the files in the hosts/ directory to get information about itself! As you’ll see in our example, we will create a file in hosts/ for machines each node will connect to as well as the node itself.

Authentication: How Each Node Knows It’s OK To Grant Access to the VPN Network.

tinc uses RSA authentication to authenticate nodes. If you’re not sure how RSA works, take a look at our RSA authentication primer. But for now, let’s suffice it to say that this is a key exchange. Each end of the node has to provide a key to be accepted by the other nodes

This means that each node has to have its own public / private RSA key pair. But don’t let that intimidate you, we’ll show you had to make these without having a Ph.D. in mathematics.

Preparing Your Computer

Whether you are running a server or a workstation, you have to make sure you have fulfileld the system requirements for tinc. They are:

  • A kernel that supports tun/tap. If you are using a modern version of any Debian based system, you’re already set here. (This includes Debian, Ubuntu, Mint, and other flavors). Most other modern Linux systems support this right out of the box. Except those distros that require you compile the kernel in order to install… but then again, if you’re using one of those experts-only distros, you won’t need much help installing this feature.
  • Make sure you have the following packages installed and available:
  1. OpenSSL
  2. zlib
  3. lzo

How to Install tinc-VPN

In Debian based systems, this is easy. Just use

apt-get install tinc

Do this for all the machines that will be participating in the VPN.

Setting up the Network

Do it on Paper First! Write down:

  1. Public IP of the “server”.
  2. VPN IP of the “server”.
  3. VPN IP of the “client(s)”

In our case, we are going to assume:

  • Public IP of the “server”: 12.345.67.89.
  • VPN IP of the “server”:
  • VPN IP of the client:

How To: Setting up the tincd “Server”

Setting up the “server” simply means we need to setup the files tinc uses in the order that it uses them:

  1. nets.boot
  2. the network directory
  3. tinc.conf in the network directory
  4. the hosts directory for the network
  5. the individual host files for hosts on the network.
  6. tinc-up
  7. tinc-down

First, change to the /etc/tinc/ directory, and edit the nets.boot file. We are going to add a single line to the end of the file: myvpn.

echo 'myvpn' >> nets.boot

Next, create the myvpn folder under /etc/tinc because tincd is going to look in that folder after it discovers that nets.boot has “myvpn” as one of the entries.

mkdir /etc/tinc/myvpncd /etc/tinc/myvpn

Next, create the tinc.conf file, which tells tincd how to setup its own node. Using your favorite Linux text editor (vim!), create tinc.conf with these two lines in the file:


Save the file.

This, of course, assumes you are running a Debian based system that has a device at /dev/net/tun. Most do. But, if your distro doesn’t, you can change this to something like /dev/tap0 of you have tunctl installed. But for our example, we’re going to leave it like  this.

Now, if you remember from our order of operations above, as soon as tincd finds this file, it’s going to look for mycpn in the hosts directory. So, we need to create that directory so we can create the file.

mkdir /etc/tinc/myvpn/hosts

But we don’t create the myvpn file that goes in hosts/! That will be created for us when we generate the RSA keys for this system. So, let’s generate the keys:

tincd -n myvpn -K

If you haven’t set-up the tinc.conf file correctly (or yet), This command will generate two keys: rsa_key.priv and Both of these will appear in your /etc/tinc/myvpn/ directory (because we specified -n myvpn in the command above). These two keys represent the keys to THIS system. So, we’ll keep the private key where  it is, but let’s move the public key into hosts:

mv /etc/tinc/myvpn/ /etc/tinc/myvpn/hosts/vpnserver

If you DID correctly set-up your tinc.conf file, tincd will read that file, and find the name of this computer and use it to put the public key in the correct spot. So, instead of creating the public key as /etc/tinc/myvpn/, it should read Name=vpnserver, and put the public key in /etc/tinc/myvpn/hosts/vpnserver.

Right now, that file (/etc/tinc/myvpn/hosts/vpnserver) only contains the RSA public key, but we need to add some more information about this node to that file. So, let’s edit that file:

vim /etc/tinc/myvpn/hosts/vpnserver

and add some lines to it to identify the node both to itself, and later, to the other nodes on the network. We’ll add two lines: Subnet and Address.

Subnet identifies the IP address this node will have on the VPN network. Address identifies (to other nodes) what IP address they should use to connect to this server.

Subnet= RSA PUBLIC KEY-----MIIBCgKCAQEAoEgxyY5DANAlKSP3pkHJvX5Co1uihxcCwFGW7G3bXUsKTkg6TE1Pqs7Fae9HQIYPzu0uHhjR0jFNP0rAEWl3VoQnpe3E6uIBs+8PWlIpB6OvLXjaYbo7FhCje3OYTQMDwbhGaeZ/TdoOvAhHlu8giHZFc4SZ/Bd4z58UmLC5ShAtHKhMJr6KdYsZjBWnz341Q/dY+NRW5RXpH8akt8yW7xw/9So8CM3Lyf9Vvtn1RyY0IJcIq1kVUXYOmx/j5Ef48GrbziF5DhEhYCqVSYzqfeIS0PKesNyTWvqr0/n2owSH3q5a2mNIb+DuppRFSWxzkymrvrGfxVRuhi1Hj5lQPwIDAQAC-----END RSA PUBLIC KEY-----

Lastly, we need to set-up the tinc-up and tinc-down scripts. These scripts execute automatically when the VPN network comes up and when the VPN network goes down (respectively).

Essentially, we need these scripts to create the interface that the computer will use to talk to the VPN network when the VPN comes up, and then remove it when the VPN service stops.

Create a file called /etc/tinc/myvpn/tinc-up, and put the following lines of code in it:

#!/bin/bashifconfig $INTERFACE netmask

Because tincd runs in router mode by default, we do not need to put any other configurations (or routes) in this file because tincd will build and maintain routing tables for us.

Now for tinc-down, which will execute when we shut down tinc and disconnect from the VPN. Create a file: /etc/tinc/myvpn/tinc-down, and add this content.

#!/bin/bashifconfig $INTERFACE down

This removes the vpn adapter from the system when the vpn service is shut down.

Once you have created those two files, you have to grant them permission to execute:

chmod +x /etc/init.d/myvpn/tinc-*

Now, you’re ready to start the tinc vpn server:

/etc/init.d/tinc start

If all goes well, you should see the following in syslog:

tincd 1.0.19 (Apr 22 2013 21:45:36) starting, debug level 9/dev/net/tun is a Linux tun/tap device (tun mode)Executing script tinc-upListening on port 655Listening on :: port 655Ready

If you see any errors, google them, fix them, and then restart tinc until the errors resolve.

Setting up the VPN Clients

Because a “server” and a “client” have just ONE difference (the Server doesn’t use a ConnectTo directive in tinc.conf), The basic setup is exactly the same. So, follow the steps above to setup your client(s), but note these differences in /etc/tinc/myvpn/tinc.conf:

  • Clients will use a “ConnectTo” directive.
  • Clients need to be uniquely named. The server uses Name=vpnserver, but the clients should have their own individual (unique) network names. Name=Client01 would work, so would Name=George.

There is two major differences for clients in the public rsa key, which is stored in hosts/ for the network:

  • The Name directive must be unique
  • The subnet must be a different IP for the client than the server has.

Here is an example tinc.conf for a client:


Notice the Name is unique (this is for “George’s computer”) and it also uses the ConnectTo directive to tell this client node to connect to the main vpn server node.

Here is an example /etc/tinc/myvpn/hosts/George01 file:

Name=George01Subnet= RSA PUBLIC KEY-----MIIBCgKCAQEAzkkYpNIWSrm1kNX49PXYZR4SALGUtDY/iKHVGF2oqvsoKhl5hENiiNw9QqUtKUSDuJxP8w2AbeHBYaqr9kVyw3c/2Vzp1oGIxpbtMRcSEDJUcgJlpNeJ8iEvjEPUiliLNrfnpu7dEk8gT6Fu+b94R1n/5JnLueny3i0p8+qbA5/z4KUqVQCHnQqcDQ+8DY2Otrljae6YwEMgtShtUNA6nkUfJ61Y/2UITL6RQP7rAXbn3kJYozm/gjJPQ4W0oUlTSFwM2qziGIj68KrUXBj6V3VjInuVdAgFii6B2aXI+qUst705B/Bw+BZIsQxiKNruU+gi/+aQx2mtP2YPiTYk1QIDAQAB-----END RSA PUBLIC KEY-----


  • the file name matches the Name directive in the /etc/tinc/myvpn/tinc.conf file.
  • The Subnet is different than the server. In this case, it is the next available address, but it doesn’t half to be. It could be any address on the network.

Now, your client is setup! Start the tincd service and watch /var/log/syslog for errors that need correcting:

/etc/init.d/tinc start

The Last Step: Exchanging Keys

As mentioned in the introduction as well as in our RSA Authentication Primer, both sides of the VPN need to exchange public keys so that the “conversation” can actually take place.

So, let’s use secure copy to copy the vpnserver public key to the client. From the client:

cd /etc/tinc/myvpn/hostsscp root@12.345.67.89:/etc/tinc/myvpn/hosts/vpnserver .

If (when) prompted to enter your password, enter the password for the VPN server’s root account.

Now, let’s send the client public key to the vpn server:

cd /etc/tinc/myvpn/hostsscp George01 root@12.345.67.89:/etc/tinc/myvpn/hosts

Testing Your Connection

If all has gone well, you’ll now be able to ping the machines over the vpn network. From the “client” node:

ping -c4

should give you:

PING ( 56(84) bytes of data.64 bytes from icmp_req=1 ttl=64 time=1.15 ms64 bytes from icmp_req=2 ttl=64 time=0.905 ms64 bytes from icmp_req=3 ttl=64 time=0.979 ms64 bytes from icmp_req=4 ttl=64 time=0.943 ms

Form the server node, you should be able to execute:

ping -c4

and get:

PING ( 56(84) bytes of data.64 bytes from icmp_req=1 ttl=64 time=1.15 ms64 bytes from icmp_req=2 ttl=64 time=0.905 ms64 bytes from icmp_req=3 ttl=64 time=0.979 ms64 bytes from icmp_req=4 ttl=64 time=0.943 ms

Special Thanks

Special thanks to Guus Sliepen, who not only developed tinc-vpn, but also generously provides support via his tinc-vpn mailing list

Creating a Network Lab for Server Pre-Deployment

Wouldn’t it be wonderful if you could prepare a network lab that would allow you to build a server and fully test it (including the production network configuration) before deploying it to a client’s office? As an IT consultant, you will reap many benefits by fully testing a server or a system in a network lab before it ever hits the client’s office. For starters, if something breaks, is mis-configured, doesn’t work, or is just plain wrong, you can fix it at your leisure and without the client ever knowing you made a mistake. If you try to build out servers and systems at the client’s office, however, they are going to see every hiccup and every mistake, which damages your credibility with them.

In this article, I will teach you how to build a network lab that you can use to completely re-create your client’s network inside your own lab, so that not only can you build the server before you give it to the client, but you can fully test it (including it’s network configuration) before deploying it.

Understanding the Concept

Essentially, we are going to create two, concentric networks inside your existing LAN. (This makes a grand total of three concentric networks with an internet connection.)

In order to create each of these concentric networks, we’ll need to configure a router to route traffic appropriately between them. For the sake of simplicity, just know that with every router, a new circle is created. And, the router doesn’t care that the circle you are creating is a private or public network. It just routes traffic.

By definition, a router is a device that joins two networks together. The secret is: it doesn’t care what the networks are. While IP address calculation and subnetting are outside the scope of this article, I will tell you that you can create a small network inside your network that will mimic the public internet at your client’s place.

Terms Used in this Article

PseudoWAN: The emulated WAN or public internet connection we create inside your LAN, which serves to mimic your client’s internet connection.

PseudoLAN: The emulated local area network that is inside your LAN, which serves to emulate your client’s LAN.

AlphaRouter: The router that connects your LAN to the PseudoWAN (and by virtue of its existence and configuration, creates the PseudoWAN inside your LAN.)

AlphaSwitch: The switch that lives in the PseudoWAN.

BetaRouter: The router that connects the PseudoLAN to the PseudoWAN (and by virtue of its existence and configuration, creates the PseudoLAN).

BetaSwitch: The swith that lives inside the PseudoLAN.

Network Universe: The entirety of the three concentric networks, which include your LAN, the PseudoWAN, and PseudoLAN

What Hardware You’ll Need


To do this, we are going to need two routers in addition to the one you are already using, some cables, and the computers you are going to hook up to test in configuration.For the purposes of this article, we are going to use a Linksys WRT54G, but most any router that allows you to fully configure both the WAN address and the LAN address will do. (If you’re lucky enough to have a WRT54GL and can put either the Tomato firmware or DD-WRT on it, that’s even better!).

Your Client’s Network Topography

You’ll need to know what his IP addresses are. Smaller offices use a 192.168.x.x/24 network. You’ll need to figure out what they are using so you can properly configure your pseudo network.

Your Client’s ISP Configuration

You’ll need to get your client’s IP address block information so you can successfully create the pseudo public internet. For the purposes of this tutorial, we are going to use a 6 host block, which gives us 5 usable IP addresses. The IP addresses we have available are:


Our gateway is, and the network is (this is the same as with a subnet mask of

So, our IP configuration for our first usable IP is going to be:


We will make this the firewall address.

Our second usable address will be configured to be a server. It’s network configuration will be:


Map Out Your Network Lab

I highly advise that you draw out what you’re about to make and put in the relevent IP addresses for all the equipment. It will make it a lot easier to understand and a lot more efficient to build. Below, you will find the network map of the example Network Universe we are building. You can see that it flows from top to bottom, from the internet, to the LAN, to the pseudo public network for the client, to the client’s pseudo network. Be sure to come back to this diagram and reference it as you read the rest of this tutorial and even as you build your own network universe.

Mimicking  the Public Internet

To create our own, personal, version of our client’s internet connection, we’ll need to configure the first router to create the same network conditions that exist at our client’s office. Thus, we need to create a gateway for their block of public IP addresses. So, let’s grab our Linksys router, and configure the WAN and LAN sides of the router so it will act like our client’s ISP’s gateway.

WAN is LAN and LAN is WAN!

The WAN port of the Linksys router will need to be configured as an address on your local LAN. This allows the router to pass information into your LAN from our pseudo networks. So, let’s configure it to be

Now, let’s configure the LAN side to be the gateway of the WAN for the client. Enter your client’s public gateway IP address in for the LAN IP address of the router, configure the gateway, and disable the DHCP server, then click save.

Now, plug the WAN port from this router into the switch on your network, and plug the LAN port into a switch. Your public network is now operational.

Installing Your Public Server in the PseudoWAN

  1. Connect your server’s LAN card to the switch, which is connected to the router we just setup.
  2. Configure the network card of your server with the following:

Restart the networking services if necessary, and use ping to verify you can ping the gateway Next, use ping to verify that traffic from the PseudoWAN is traversing the router properly and entering your LAN: ping your gateway ( Lastly, confirm that network traffic can get from your PseudoWAN, through your network, and out on to the public internet by pinging Google’s DNS Servers:

Assuming that all three of these ping tests receive replies, you are clear to move to the next step. If you get packet losses at any of the steps above, go back, and reconfirm your settings.

Setting Up the PseudoLAN

This process is done with a second router. You can use the same make and model router as you used before. They do not have to be different. Again, we are using a WRT54G in the examples.

1. Plug the WAN port of the BetaRouter into the AlphaSwitch.

2. Configure the WAN port of the BetaRouter with the following:


3. Configure the LAN

First, you’ll need to change the LAN IP address, and click Save / Updatebecause until you do that, the DHCP server range will be inaccurate. Once you have done that, you can configure the DHCP server range, and click save / update again. Configure the LAN IP of this router to be the gateway of the PseudoLAN, which mimics the LAN in your client’s office.

Add Client Computers to the PseudoLAN

At this point, you can add a computer to the PseudoLAN, and give it an IP address that is identical to what it would have while in production at your client’s office. Once you have a computer setup, use ping to verify connectivity from that computer to the PseudoLAN gateway (, the PseudoWAN gateway (, your LAN gateway (, and finally the public internet (Google’s DNS at When all those tests come back positive with good replies, you have successfully built your network universe to parrot your client’s network so you can build and install!