Ubuntu 16.04
虚拟网络设备tun
安装
最近编写网络程序,需要用到tun
模块,但是官方给的发行版中压根就没有这个模块.
不信的话,你可以测试一下:
root@ubuntu:~# modinfo tun
modinfo: ERROR: Module tun not found.
当然,如果你测试的结果是这样的:
root@ubuntu:~# modinfo tun
filename: /lib/modules/4.8.17/kernel/drivers/net/tun.ko
alias: devname:net/tun
alias: char-major-10-200
license: GPL
author: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
description: Universal TUN/TAP device driver
srcversion: 7CDF0549396A7B788E3753B
depends:
intree: Y
vermagic: 4.8.17 SMP mod_unload modversions
只能说明你可能已经安装了,但是还要进一步测试,运行下面两条命令,如果得到类似下面的结果,那么这篇文章后面的东西你就不用看了,如果没有任何输出,那么你估计要重新安装一下tun
模块了.
root@ubuntu:~# modprobe tun
root@ubuntu:~# lsmod | grep tun # 列出所有的模块,在其中寻找tun
tun 28672 0
接下来我会详细记录一下我解决这个东西时遇到的一些问题,也是为了方便以后的查看吧.
如果你懒得查看下面的内容,其实有一个更好的办法,那就是更换一个已经包含了tun
模块的linux
发行版.这里我强烈推荐deepin
,真正适合不折腾的人.对于国人来说,这个发行版比ubuntu
更加舒服和漂亮.
1. 下载源码
lishuhuakai@ubuntu:~$ sudo apt-get install linux-source
linux-source linux-source-4.10.0 linux-source-4.4.0 linux-source-4.8.0
使用apt-get
命令安装linux
源代码,一般你按tab
键的时候,会有很多的选择,比如说上面,我就有4.4.0
, 4.8.0
, 4.10.0
这几个版本可供选择,到底选择哪一个呢?这个看你个人的爱好了,但是有一点需要注意,尽量不要选择比自己内核版本低,或者比当前内核版本高太多的版本,高太多的话,linux
内核高版本对低版本并没有保持非常好的兼容性,所以你要是一下子版本跨越太大,可能内核升级之后,系统都跑不起来.
因为我们并不需要升级内核,所以应该选择一份和自己内核版本号相近的源码.
可以用uname -a
来查看当前内核版本号:
lishuhuakai@ubuntu:~$ uname -a
Linux ubuntu 4.8.17 #1 SMP Thu Apr 20 04:16:43 PDT 2017 x86_64 x86_64 x86_64 GNU/Linux
可以看到,我当前的内核版本是4.8.17
,所以我选择一个4.8.0
的版本即可.源码一般会被安装到/usr/src/linux-source-x.x.x/
目录下,x.x.x
是版本号,拿我的机子做个示例:
lishuhuakai@ubuntu:~$ cd /usr/src/linux-source-4.8.0/
lishuhuakai@ubuntu:/usr/src/linux-source-4.8.0$ ls
debian debian.hwe linux-source-4.8.0.tar.bz2
可以看得到,在这个目录下有一个压缩文件linux-source-4.8.0.tar.bz2
,这就是源码的压缩文件,当然,对应到你的机器上,版本号可能会有所不同.
2. 解压缩文件
如果你使用虚拟机的话,请保证空间一定要足够大,因为后面的压缩以及编译都需要不少的空间.
lishuhuakai@ubuntu:~$ tar xvjf linux-source-4.8.0.tar.bz2
进入解压好的目录,为了方便操作,接下来的操作都切换到root
账户下,所以我们干脆就不显示root
了:
cd linux-source-4.8.0/
3.配置选项
为了后面编译不出错,我们先安装libncurses5-dev
,执行命令:
apt-get install libncurses5-dev
即可.
然后配置需要编译的模块:
make menuconfig
然后你大概就能够看到这样一副图像,找到Device Drivers -->
,回车选择:
继续找到Network Device Support -->
,回车选择:
找到Universal TUN/TAP device driver support
,看到前面是<*>
,键盘输入M
,变成<M>
,退出并保存,回到终端:
注:[*]
,<*>
表示编译进内核,<M>
表示编译成模块,如果不知道某选项为何时,且有模块可选时,那么就可以直接选择为模块,如果有疑惑,可以去翻鸟哥的linux私房菜基础篇
这本书.
4. 编译模块
开始执行命令:
make modules
事实上,上面的编译速度太慢,如果你要加快编译速度的话,可以使用-jn
选项,n
是一个数字,表示用n
个线程并行编译.比如说我这台电脑的话,就是这么干的:
make -j4 modules
使用4
个线程,因为我的电脑是双核四线程的cpu
,编译的时候cpu使用率可以达到100%
,当然,我可以设置-j8
或者更高,但是没有意义,当然,如果你的电脑是8
线程,那么推荐用-j8
,16
线程推荐用-j16
,能快一点最好不过了.
5. 复制加载模块
编译完成后,可以想内核中加载模块了:
cp /usr/src/linux-source-4.8.0/linux-source-4.8.0/drivers/net/tun.ko /lib/modules/4.8.0-36-generic/kernel/net/tun.ko
上面的命令是在我的机器上的做法,你的机器可能由于版本号的不同会有所差异.总之要干的事情就是将编译过后的tun.ko
复制到/lib/modules/xxx/kernel/net/
目录下去,xxx
是一个和你当前内核版本号相关的目录,一般而言,这个目录下也就xxx
这么一个目录.
接下来是分析可载入模块的相互依赖性:
depmod
6. 验证和加载
和文章最开始的套路是一样的,如果得到类似下面的输出,基本上你的安装就成功了.
root@ubuntu:~# modinfo tun
filename: /lib/modules/4.8.17/kernel/drivers/net/tun.ko
alias: devname:net/tun
alias: char-major-10-200
license: GPL
author: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
description: Universal TUN/TAP device driver
srcversion: 7CDF0549396A7B788E3753B
depends:
intree: Y
vermagic: 4.8.17 SMP mod_unload modversions
root@ubuntu:~# modprobe tun
root@ubuntu:~# lsmod | grep tun
tun 28672 0
当然,也有可能会失败,事实上,我编译了几次都失败了,每次验证的时候,执行到modprobe tun
的时候,都会输出类似与下面的错误信息:
modprobe: ERROR: could not insert 'tun': Exec format error
事实上你可以用dmesg
查看错误的原因,下面是用该命令输出的最后一行:
[ 51.803686] tun: no symbol version for module_layout
网上查看了一下别人的资料,我觉得可能的一个原因是内核的版本不匹配,因为我之前使用的内核版本和我编译的内核版本版本存在差异,网上有解决方案,但是不适合我,如果你想节约时间的话,可以查看这里:http://www.snooda.com/read/329
既然上面的步骤都不行,我干脆重新编译一下内核好了:
7. 最后的选择,重新编译内核
事先说明一句,我的操作都在虚拟机上完成,如果你在真机上测试的话,可能不太妥当,所以如果你使用真机,强烈建议你别人的博文中看一下别人是如何编译内核的.
回到之前源文件解压的目录,首先要配置config
文件, 可以直接复制旧版本的:
cp /boot/config-3.19.0-81-generic ./.config
接下来执行:
make oldconfig
注:复制的是当前版本的config
,所以执行这条命令会让你选择新版本多出来的选项,按回车键用默认的新设置.
也可以直接用以下命令进入图形化的设置界面,也就是我们前面所使用的命令:
make menuconfig
这里需要按照前面的步骤,选择Universal TUN/TAP device driver support
,设置好后保存退出即可.
接下来就可以编译了:
make -j4 # 开启4个线程并行编译
事先说明一句,编译需要占用大量的空间,我给虚拟机分配了20GB
的空间,但是依旧被填满了,所以,如果你也使用虚拟机的话,我个人建议你分配30GB
或者更大的空间来编译内核.至于如何给虚拟机添加空间,就不是这篇文章的事情了.
编译的过程中可能会出现两个错误,第一个错误是fatal error: openssl/opensslv.h: No such file or directory
,
这是因为没有安装openssl
的,需要先安装openssl
:
apt-get install libssl-dev
第二个错误是bc: not found
,需要安装bc
:
apt-get install bc
编译可能会花费1~2个小时.完成之后,先安装modules
:
make modules_install
接下来安装内核:
make install
一切完成之后,重新启动电脑,一切就都完成了.接下来你就可以用上面的办法来检测了.