FreeBSD 下用OpenVPN 架设虚拟局域网

来源:互联网 发布:如何处理淘宝图片 编辑:程序博客网 时间:2024/05/18 16:18

2007-09-07 11:32:07
 标签:FreeBSD 虚拟局域网 OpenVPN   [推送到技术圈]

[url]http://www.chinaunix.net[/url] 作者:xdkui  发表于:2007-04-12 16:04:23【发表评论】【查看原文】【VPN讨论区】【关闭】
FreeBSD 下用OpenVPN 架设虚拟局域网

1 环境及需求
    4 个房间,分别通过4 个802.1X 帐号连接到学校校园网。4 个房间属于一个课题组,需要共享资料,4 个房间内计算机需要相互访问文件共享,能访问一台用于提供软件及个人备份文件共享服务器,一台Web 服务器,以及打印机。
    4 个802.1X 帐号中有一个是可以上国外网的帐号,另外3 个可以上国内网,希望4 个房间的计算机上国内网络时通过本房间的帐号出去,上国外网时都通过1 个固定的国外帐号出去。

2 解决方案
    方案:使用OpenVPN 连接4 个房间的网络组成虚拟专用网。4 个房间都有专用的电脑做该房间的网关,使用FreeBSD 系统(个人喜好,用别的操作系统配置差不多)。网关通过802.1X 拨号连接到校园网,各个房间的网络通过网关NAT 共享上网。
    A,B,C,D 房间内部分别是192.168.10.0/24,192.168.11.0/24,192.168.12.0/24,192.168.13.0/24 网段,192.168.10.1,192.168.11.1,192.168.12.1,192.168.13.1 分别是4 个房间的网关,172.16.37.83 等地址为4 个机器的校园网地址。192.168.10.1 用作vpn server,B,C,D 房间的网关分别为vpn client1,vpn client2,vpn client3(下文client 为这3 个vpn 客户端的总称)。网络结构图见图1。
[attach]161237[/attach]
[align=center]图1 网络结构[/align]
       vpn 客户端内部网络上国外网络的数据通过vpn server 的NAT 出去,上国内网络的数据通过自身NAT 出去。vpn client2 和vpn client3 上网数据的路由同vpn client1,图里没有画出。本文主要讲OpenVPN 的配置。OpenVPN 有路由VPN 和以太网桥接VPN 两种模式,桥接VPN 相当于用网桥把多个网络连接,多个网络可以使用同一个网段。本文使用路由模式,可配置性强,功能也更强。参考信息见OpenVPN Install.htm,OpenVPN 2_0 HOWTO.htm和OpenVPN 2_0_x Man Page.htm

3 安装OpenVPN
      4 台用于VPN的机器都需要安装。OpenVPN依赖OpenSSL库,加密用;LZO库,数据压缩用,不使用该库也没有关系。FreeBSD 6.0 默认安装带了OpenSSL库,就不说了。没有安装的去[url]http://www.openssl.org/[/url]下载安装即可。或者用FreeBSD的ports安装。

LZO去[url]http://www.oberhumer.com/opensource/lzo/[/url]下载源代码包。
或者用ports 安装:
cd /usr/ports/archivers/lzo && make install 即可。
源代码安装:
./configure && make && make install
比较简单,就不说了。

我用源代码安装OpenVPN,从[url]http://www.openvpn.net[/url]下载openvpn-2.0.7.tar.tar
./configure --with-lzo-headers=/usr/local/include --with-lzo-lib=/usr/local/lib && make &&
make install
如果不使用LZO 库则
./configure --disable-lzo && make && make install

4 生成证书和密钥
cd /home/xdkui/openvpn-2.0.7/easy-rsa/
vi vars
根据自己的情况设置KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG,
KEY_EMAIL,比如我的
export KEY_COUNTRY=CN
export KEY_PROVINCE=Beijing
export KEY_CITY=Beijing
export KEY_ORG=BUAA
export KEY_EMAIL="xdkui@163.com"
然后保存
. ./vars //注意两个点中间有空格
./clean-all
./build-ca
build-ca 命令使用openssl 命令生成certificate authority (CA) certificate 和密钥:
./build-ca
Generating a 1024 bit RSA private key
....++++++
.......++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [Beijing]:
Locality Name (eg, city) [Beijing]:
Organization Name (eg, company) [BUAA]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:xdkui-ca //这里随便输入即可
Email Address [xdkui@163.com]:
4.1 为vpn server 产生证书和私钥
./build-key-server server
Common Name 处填server,其他默认,为上面编辑vars 文件时设置的值。"Sign the certificate?
[y/n]" 和"1 out of 1 certificate requests certified, commit? [y/n]"两处选y。
4.2 为vpn clients 产生证书和密钥
./build-key client1
./build-key client2
./build-key client3
Common Name 处分别填client1 client2 client3,别的同vpn server 设置。
4.3 生成Diffie Hellman 参数
./build-dh
    现在生成了所需的文件。目录keys 下生成的文件中,ca.crt 是所有vpn 机器都需要的。vpn server 需要ca.crt ca.key dh1024.pem server.crt server.key,拷贝到vpn server 的/etc/openvpn目录。vpn client1 需要ca.crt client1.crt client1.key,拷贝到vpn client1 的/etc/openvpn 目录。client2,client3 和client1 同,只是client1.crt 和client1.key 分别用client2 和client3 的对应文件。vpn client2 和vpn client3 也把对应的密钥文件拷贝到各自的/etc/openvpn 目录。各个文件的用途可以参看下表(来自HOWTO):
[attach]161239[/attach]

5 配置vpn server 和client
      server.conf 使用代码包目录sample-config-files 里的server.conf 修改即可。配置文件里的
选项含义可以参考OpenVPN 2.0.x Man Page,比如keepalive, ifconfig-push 选项等。如下:
#################################################

# Sample OpenVPN 2.0 config file for #

# multi-client server. #

# Comments are preceded with '#' or ';' #

#################################################

;local a.b.c.d 绑定的IP 地址,可以不填

port 1194 绑定的端口

proto udp 选择udp 协议,也可用tcp

# "dev tun" will create a routed IP tunnel,

# "dev tap" will create an ethernet tunnel.

;dev tap

#使用tun 设备,路由IP 通道。FreeBSD 默认支持TUN/TAP 驱动。

dev tun

#下面4 处填上面为vpn server 生成的证书和密钥

ca ca.crt

cert server.crt

key server.key # This file should be kept secret

dh dh1024.pem

#配置vpn 虚拟网段,会在vpn server 建立一条10.0.0.1 >10.0.0.2 的点对点虚拟链路。

server 10.0.0.0 255.255.255.0

#记录client 对应得虚拟地址,默认600 秒更新一次

ifconfig-pool-persist ipp.txt

#等价于ping 10 和ping-restart 120,对于vpn 机器有可能断开外网联线或者重起的,

#或者vpn client 先于vpn server 运行的情况下很重要。Client 会重新连接。

keepalive 10 120

#开启压缩支持。如果编译的时候没有使用LZO 库则注释本行

comp-lzo

#初始化完成后改变OpenVPN 进程的用户ID 为nobody

user nobody

#同上,改变进程的组ID 为nobody。如果是Windows 系统,注释掉这两行

group nobody

persist-key

persist-tun

#默认每分钟更新状态文件,可以看到client 的真实IP 虚拟IP 等信息。

status openvpn-status.log

verb 3

    client1.conf 使用源代码包目录sample-config-files 里的client.conf 修改即可。如下:
##############################################

# Sample client-side OpenVPN 2.0 config file #

# for connecting to multi-client server. #

# On Windows, you might want to rename this #

# file so it has a .ovpn extension #

##############################################

client

dev tun

proto udp #和server.conf 一致即可

remote 172.16.37.83 1194 #指定vpn server 的IP 地址和端口

resolv-retry infinite #如果解析vpn server 失败则无限次重试

nobind

user nobody

group nobody

persist-key

persist-tun

ca ca.crt

cert client1.crt #这2 行填给client1 生成的密钥文件。client2 client3 相应更改。

key client1.key

comp-lzo

keepalive 10 120

      vpn client2 和vpn client3 的客户端配置文件client2.conf 和client3.conf 同上,只是改cert和key 选项为对应的密钥文件。
    对于vpn server,运行openvpn 后会建立一条本地ip 为10.0.0.1,对端ip 为10.0.0.2 的点对点虚拟链路,这样所有server.conf 里的route 选项都会路由到10.0.0.2,即openvpn 里面,然后由openvpn 处理。
    对于client,则会选在一对ip 作为客户端的点对点虚拟链路,比如本地10.0.0.10,对端10.0.0.9。并把第一次分配给client 的ip 记录在ipp.txt(server.conf 里ifconfig-pool-persist 指定)里,下次对应的client 连接的时候可以分配先前被指定的地址,但man 手册说不保证每次会指定同一个ip。
    我需要给每个client 指定固定的vpn 地址,用ifconfig-push 指令即可。Windows 下,由于TAP-Win32 驱动的限制,虚拟IP 对只能在/30 子网选择,最后2 个2 进制位,除去全0的网络地址和全1 的广播地址,虚拟IP 只能选择01 和10,故虚拟IP 对只能是[1, 2] [5, 6] [9, 10]等(详见HOWTO)。Unix 客户端则没有这个限制,可以随便设置IP,比如client 分别设置成本地IP 为10.0.0.2, 10.0.3, 10.0.4 对端IP 都为10.0.0.1。考虑到以后client 可能会用Windows,故本文中遵循这个限制。给vpn client1, vpn client2, vpn client3 分配的虚拟客户端和服务器端IP 对分别为[10.0.0.5 10.0.0.6],[10.0.0.9 10.0.0.10],[10.0.0.13 10.0.0.14]。见图2。
[attach]161238[/attach]
[align=center]图2 指定VPN 的虚拟IP 地址对[/align]
    给server.confi 添加如下行:
client-config-dir ccd

    并在vpn server 的/etc/openvpn 目录建立ccd 子目录,并在ccd 目录下建立文件client1,client2,client3(这里的文件名对应”为vpn clients 产生证书和密钥”步骤里的Common Name),当对应得client 连接时,vpn server 会读去对应文件里的配置信息。文件client1 里输入:
ifconfig-push 10.0.0.5 10.0.0.6
,即给vpn client1 指定10.0.0.5,对端10.0.0.6 的虚拟链路。
client2 内容:
ifconfig-push 10.0.0.9 10.0.0.10

client3 内容:
ifconfig-push 10.0.0.13 10.0.0.14

    分别拷贝server.conf,client1.conf,client2.conf,client3.conf 到vpn server 和对应的client。分别在各个vpn 计算机启动vpn server 和vpn client
openvpn --config /etc/openvpn/server.conf --cd /etc/openvpn/
openvpn --config /etc/openvpn/client1.conf --cd /etc/openvpn/等
    如果是Windows,改.conf 为.ovpn,然后右键选择Start OpenVPN on this config file 即可
启动。
    如果都出现“Initialization Sequence Completed”表示VPN 建立成功,否则检查vpn server的防火墙是否屏蔽了UDP 1194 端口。如果客户端是Windows,检查DHCP Client 服务是否启动。到这一步,VPN 客户端和服务端可以相互通讯了。10.0.0.1 应该可以ping 通10.0.0.5,10.0.0.9,10.0.0.13。10.0.0.5,10.0.0.9,10.0.0.13 也可以ping 通10.0.0.1。但10.0.0.5,10.0.0.9,10.0.0.13 还不能相互ping 通,即vpn 客户端之间还不能相通。

5.1 vpn client 访问vpn server 所在192.168.10.0/24 网段内计算机
      第一种方法,添加如下行到server.conf
push "route 192.168.10.0 255.255.255.0"

push 选项是把选项内容给连接的vpn 客户端执行,也就是在vpn 客户端执行“route 192.168.10.0 255.255.255.0”,即当client 连接时,添加路由到client 的路由表里。对于vpn client1,该选项相当于在vpn client1 的路由表里添加到网络192.168.10.0/24,下一跳为10.0.0.6的路由,这里10.0.0.6 为给vpn client1 分配的虚拟IP 对的服务器端IP,相当于路由到vpn server。
    第二种方法,如果不改变server.conf,在vpn client1 里route add –net 192.168.10.0 10.0.0.6 255.255.255.0 效果一样,也可route add –net 192.168.10.0 10.0.0.1 255.255.255.0 直接路由到vpn server 的本端IP 也可,但这样需要在所有的vpn 客户端改变路由表。
    这样在vpn 客户端可以ping 通192.168.10.0/24 网段内部计算机了。到此,B,C,D 房间的
网关可以访问A 房间的所有计算机了。

5.2 vpn server 访问vpn client 网段内计算机
      以vpn client1 为例,是vpn server 能访问192.168.11.0/24 网段内计算机。同样有2 种方法,一是改server.conf 让openvpn 程序添加路由,另一种是手动添加路由。
    第一种方法,添加如下行到server.conf
route 192.168.11.0 255.255.255.0

从OpenVPN 的man 手册可知,route 选项用于改变路由表。这里在vpn server 添加到网络192.168.11.0/24,下一跳为10.0.0.2 的路由,即把192.168.11.0/24 路由到openvpn 内部。然后添加如下行到/etc/openvpn/ccd/client1
iroute 192.168.11.0 255.255.255.0

告诉openvpn 192.168.11.0/24 的网段路由到vpn client1。route 选项用于修改从操作系统内核到OpenVPN 服务端的路由,iroute 用于控制OpenVPN 服务端到OpenVPN 客户端的路由。现在从vpn server 或者其内部192.168.10.0/24 内机器都能ping 通192.168.11.0/24 内部的机器了。
    第二种方法,手动修改vpn server 路由表,route add -net 192.168.63.0 10.0.0.2
255.255.255.0 或者route add -net 192.168.63.0 10.0.0.5 255.255.255.0然后添加iroute 192.168.11.0 255.255.255.0 到/etc/openvpn/ccd/client1(注意:两种方法都必须有这一步)。
    可以明显看到修改OpenVPN 配置文件的方法要简便些,不用顾及VPN 计算机分配的虚拟IP,对于多个VPN 客户端,只需要修改server.conf 即可,而且路由条目都是建立VPN时动态添加,VPN 断开时自动删除。本文选择这第一种方法配置VPN。提到两种方法是想说明OpenVPN 里的选项对于操作系统路由的影响,用于对比,更能理解OpenVPN 的选项。
    vpn client2 和vpn client3 的修改类似vpn client1。总结所有修改如下:
添加如下行到server.conf
route 192.168.11.0 255.255.255.0 #使vpn server 能访问B 房间计算机

route 192.168.12.0 255.255.255.0 #使vpn server 能访问C 房间计算机

route 192.168.13.0 255.255.255.0 #使vpn server 能访问D 房间计算机

添加如下行到vpn server 里/etc/openvpn/ccd/client1
iroute 192.168.11.0 255.255.255.0 #B 房间计算机路由到client1
添加如下行到vpn server 里/etc/openvpn/ccd/client2
iroute 192.168.12.0 255.255.255.0 #C 房间计算机路由到client2
添加如下行到vpn server 里/etc/openvpn/ccd/client3
iroute 192.168.13.0 255.255.255.0 #D 房间计算机路由到client3
到这一步,A 房间的计算机能访问B,C,D 房间的所有计算机了,B,C,D 房间的计算机
也能访问A 房间的计算机了。

5.3 各个vpn client 之间的网段相互访问
下面配置B,C,D 房间的计算机相互访问。
添加如下行到server.conf:
client-to-client
这样B,C,D 房间的网关(即10.0.0.5,10.0.0.9,10.0.0.13)可以相互ping 通了。现在B,
C,D 房间的网关还没有到相互内部网段的路由。类似上面push vpn 服务端的内部网段到vpn
客户端,添加如下行到server.conf
push "route 192.168.11.0 255.255.255.0"

push "route 192.168.12.0 255.255.255.0"

push "route 192.168.13.0 255.255.255.0"
分别在vpn client1,vpn client2,vpn client3 添加3 条路由,对于vpn client1,192.168.11.0/24是其内部网段, vpn client1 上的openvpn 程序不会执行"route 192.168.11.0 255.255.255.0"选项,可以从openvpn 启动的信息看出。同上面一样,也可以手动修改3 个VPN 客户端的路由表,这里就不说了。到这一步,A,B,C,D4 个房间的计算机都可以相互访问了。

6 配置出国和非出国数据的路由(只是理论想法,由于所在校园网还没通,没有测试)
    A房间网关,即vpn server,使用可以上国外网的802.1X 帐号,3 个vpn client3 使用只能上国内网的帐号。在server.conf 中利用push 选项在vpn 客户端添加路由,把国外IP 地址路由到vpn server,并通过vpn server 的NAT 出去,不需要修改vpn 客户端设置。这样,vpn客户端所在的B,C,D 房间的计算机上国内网直接通过他们的网关出去,上国外网则路由到A 房间网关再出去。A 房间的上网数据都通过A 房间网关出去。当然,也可以不修改server.conf,直接在3 个vpn 客户端手动添加路由。
添加如下行到server.conf:
#下面是国外网络的网段
push "route xxx.xxx.xxx.xxx 255.255.255.0"
……..

7 总结
    在vpn server 的/etc/rc.local 文件添加如下行:
openvpn --config /etc/openvpn/server.conf --cd /etc/openvpn/ &
    在vpn client1 的/etc/rc.local 文件添加如下行:
openvpn --config /etc/openvpn/client1.conf --cd /etc/openvpn/ &
     vpn client2 和vpn client3 类似vpn client1。使openvpn 程序在系统启动时自动运行。
   修改vpn server 的防火墙配置,我使用ipfw 防火墙。添加如下规则允许通过vpn server
的侦听端口。
pass in quick on rl0 proto udp from any to any port = 1194 keep state
    在vpn server安装Apache+phpBB为内部论坛,4 个房间所有计算机浏览[url]http://10.0.0.1[/url]即可
访问。在vpn client1 安装Samba做文件共享服务器,浏览//10.0.0.5即可访问到共享。打印机
安装在A房间的内部Windwos计算机上,通过共享安装网络打印机即可。
    这样完成了所有的配置。下面总结如下:
    vpn server 的目录/etc/openvpn 下有文件ca.crt,ca.key,dh1024.pem,server.crt,server.key和server.conf 以及子目录ccd。/etc/openvpn/ccd 目录下有文件client1,client2 和client3。
/etc/openvpn/server.conf 内容如下:
;local a.b.c.d

port 1194

proto udp

dev tun

ca ca.crt

cert server.crt

key server.key # This file should be kept secret

dh dh1024.pem

server 10.0.0.0 255.255.255.0

ifconfig-pool-persist ipp.txt

keepalive 10 120

comp-lzo

user nobody

group nobody

persist-key

persist-tun

status openvpn-status.log

verb 3

client-config-dir ccd

#使vpn clients 能访问vpn server 内部网段计算机

push "route 192.168.10.0 255.255.255.0"

route 192.168.11.0 255.255.255.0 #使vpn server 能访问B 房间计算机

route 192.168.12.0 255.255.255.0 #使vpn server 能访问C 房间计算机

route 192.168.13.0 255.255.255.0 #使vpn server 能访问D 房间计算机

client-to-client #使vpn clients 相互之间可以访问

push "route 192.168.11.0 255.255.255.0"

push "route 192.168.12.0 255.255.255.0"

push "route 192.168.13.0 255.255.255.0"

/etc/openvpn/ccd/client1 内容如下:

ifconfig-push 10.0.0.5 10.0.0.6

iroute 192.168.11.0 255.255.255.0

/etc/openvpn/ccd/client2 内容如下:

ifconfig-push 10.0.0.9 10.0.0.10

iroute 192.168.12.0 255.255.255.0

/etc/openvpn/ccd/client3 内容如下:

ifconfig-push 10.0.0.13 10.0.0.14

iroute 192.168.13.0 255.255.255.0

    vpn client1 的目录/etc/openvpn 下有文件ca.crt,client1.crt,client1.key 和client1.conf。
/etc/openvpn/client1.conf 内容如下:
##############################################

# Sample client-side OpenVPN 2.0 config file #

# for connecting to multi-client server. #

##############################################

client

dev tun

proto udp

remote 172.16.37.83 1194

resolv-retry infinite

nobind

user nobody

group nobody

persist-key

persist-tun

ca ca.crt

cert client1.crt

key client1.key

comp-lzo

verb 3

keepalive 10 120

    vpn client2 和vpn client3 类似vpn client1。这里就不说了。

附件包括pdf版文档,参考资料及各个配置文件。

[ 本帖最后由 xdkui 于 2006-11-28 14:51 编辑 ]



网络结构




VPN




表1
本文出自 51CTO.COM技术博客

 

原创粉丝点击