OpenVPN使用User/Pass验证登录

在之前的OpenVPN+CA中已经介绍了使用CA验证登录的方式,详见:
http://bbs.chinaunix.net/forum/viewtopic.php?t=503434&show_type=new

本文主要介绍使用Username/Password方式验证登录VPN的方法,虽然使用的是User/Pass
方式登录,但是在Server端仍然需要证书,这样的VPN和web的HTTPs方式有点类似(不能等同),
只需Server端有证书,Client可以不提供自己的证书,Client只需验证Server的合法性即可,
所以Client端只需ca.crt(根证书)即可。当然,由于Client不是使用证书验证的,所以安全
性方面必然有所下降,但是省去了烦琐的CA管理,我们可以通过用户名和密码来登录VPN,
这样使得VPN可以很容易和论坛、邮件系统或者其他统一验证系统结合,使用现成的管理界面。

关于VPN的一些初步认识,可以从下面这个URL获得:(E文的)
http://blog.chinaunix.net/resserver.php?blogId=2389&resource=OpenVPN%20and%20the%20SSL%20VPN%20Revolution.pdf
原文出自:
http://www.giac.org/certified_professionals/practicals/gsec/3985.php
文中觉得很有意义的语句是: A VPN is a site-to-site tunnel. Let me say that one more time, a VPN is a site-to-site tunnel.
这篇文章介绍了OpenVPN1.x,也简单介绍了OpenVPN 2.x的一些新特性,同时也简单的介绍了
其他VPN以及不同方式实现的VPN产品、软件,有时间看看是很有必要的。

关于VPN比较通俗的理解,在OpenVPN的FAQ中找到的:
Imagine you had a direct physical wire (i.e. a long cable) connecting two computers (A and B) at different locations. On each computer there would be a /dev/longcable which would be a network device. You could route IP traffic over it, and do everything you could normally do with a network device.

下面开始介绍VPN的安装和配置:

环境:
OS: FC2 (在公司网络出口处,作路由或者是NAT设备使用)
eth0: 61.1.1.2 (外网地址,直接与Internet相连)
eth1: 192.168.0.1 (内网地址,连接公司内部,假设公司内部使用192.168.0.0/22这4个C地址)

Client端硬件及网络环境配置:
OS: Windown 2000 XP 为主,部分Linux (配置文件通用)
单网卡,IP地址不固定

需要达到的目的:
VPN Client可以随处通过User/Pass登录VPN,访问内网资源。

Server端配置

首先检查pam-devel包是否安装,否则从系统盘安装改软件包
[root@vpn ~]# rpm -qa | grep pam
pam_smb-1.1.7-3.1
pam-0.77-40
pam_krb5-2.0.10-1
pam-devel-0.77-40
[root@vpn ~]#

检查Mysql是否安装,确认mysql-devel包已经安装,否则从系统盘安装改软件包
[root@vpn ~]# rpm -qa | grep mysql
mysql-3.23.58-9
mysql-server-3.23.58-9
mysql-devel-3.23.58-9
[root@vpn ~]#

检查lzo包是否有安装,如果没有,可以到http://rpmfind.net去找
[root@vpn ~]# rpm -qa | grep lzo
[root@vpn ~]# wget
[root@vpn ~]# rpm -ivh lzo-1.08-3.1.fc2.dag.i386.rpm
[root@vpn ~]# wget
[root@vpn ~]# rpm -ivh lzo-devel-1.08-3.1.fc2.dag.i386.rpm
[root@vpn ~]# rpm -qa | grep lzo
lzo-devel-1.08-3.1.fc2.dag
lzo-1.08-3.1.fc2.dag
[root@vpn ~]#

下面开始编译安装OpenVPN
[root@vpn ~]# wgethttp://mesh.dl.sourceforge.net/sourceforge/openvpn/openvpn-2.0_rc16.tar.gz
[root@vpn ~]# rpmbuild -tb openvpn-2.0_rc16.tar.gz
[root@vpn ~]# cd /usr/src/redhat/RPMS/i386/
[root@vpn /usr/src/redhat/RPMS/i386]# rpm -ivh openvpn-2.0_rc6-1.i386.rpm

为了能使用OpenVPN的PAM验证插件,我们安装pam_mysql使用MySQL数据库存储用户数据,其它数据库可以找相应的PAM验证模块
[root@vpn ~]# wgethttp://internap.dl.sourceforge.net/sourceforge/pam-mysql/pam_mysql-0.5.tar.gz
[root@vpn ~]# tar -zxvf pam_mysql-0.5.tar.gz
[root@vpn ~]# cd pam_mysql
[root@vpn ~]# make
[root@vpn ~]# cp pam_mysql.so /lib/security/

配置数据库
以管理员身份登录数据库:
mysql> create database vpn;
mysql> GRANT ALL ON vpn.* TO vpn@localhost IDENTIFIED BY ‘vpn123’;
mysql> flush privileges;
mysql> use vpn;
mysql> CREATE TABLE vpnuser (
   ->   name char(20) NOT NULL,
   ->   password char(128) default NULL,
   ->   active int(10) NOT NULL DEFAULT 1,
   ->   PRIMARY KEY (name)
   -> );
mysql> insert into vpnuer (name,password) values(‘elm’,password(‘elm’));

#创建vpn用户,对vpn这个database有所有操作权限,密码为vpn123
#active不为1,无权使用VPN
#增加用户 用户名:elm 密码:elm

配置pam_mysql模块
创建/etc/pam.d/openvpn文件,文件内容如下:
===================CUT Here================
auth    sufficient      pam_mysql.so                    user=vpn passwd=vpn123 host=localhost db=vpn
       table=vpnuser usercolumn=name passwdcolumn=password
       where=active=1 sqllog=0 crypt=2
account required        pam_mysql.so                    user=vpn passwd=vpn123 host=localhost db=vpn
       table=vpnuser usercolumn=name passwdcolumn=password
       where=active=1 sqllog=0 crypt=2
==================Cut Here=================
crypt(0) — Used to decide to use MySQL’s PASSWORD() function or crypt()
           0 = No encryption. Passwords in database in plaintext. NOT recommended!
           1 = Use crypt
           2 = Use MySQL PASSWORD() function

下面可以测试pam_mysql是否工作正常,先检查saslauthd是否安装:
[root@vpn ~]# rpm -qa | grep sasl
cyrus-sasl-plain-2.1.18-2
cyrus-sasl-md5-2.1.18-2
cyrus-sasl-devel-2.1.18-2
cyrus-sasl-2.1.18-2
[root@vpn ~]#

有cyrus-sasl-2.1.18-2应该就可以了,如果没有请安装相应的软件包,不安装也行,可以通过其它方法测试

[root@vpn ~]# saslauthd -a pam
[root@vpn ~]# testsaslauthd -u elm -p elm -s openvpn
0: OK "Success."
[root@vpn ~]#

恭喜,pam_mysql工作正常了,下面可以开始配置OpenVPN服务器了。

配置VPN Server:
[root@vpn /usr/src/redhat/RPMS/i386]# cd
[root@vpn ~]# cp -r /usr/share/openvpn/easy-rsa/ /etc/openvpn/
[root@vpn ~]# cd /etc/openvpn/easy-rsa/
[root@vpn /etc/openvpn/easy-rsa]# vi vars
修改vars 文件
—————————————–
# 定义你所在的国家,2个字符
export KEY_COUNTRY=CN
# 你所在的省份
export KEY_PROVINCE=Liaoning
# 你所在的城市
export KEY_CITY=Shenyang
# 你所在的组织
export KEY_ORG="ELM OpenVPN ORG"
# 你的邮件地址
export KEY_EMAIL="elm@elm.freetcp.com"
—————————————–

#使修改的环境变量生效

[root@vpn /etc/openvpn/easy-rsa]# . vars
NOTE: when you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys

#初始化keys目录

[root@vpn /etc/openvpn/easy-rsa]# ./clean-all

#生成Root CA证书,用于签发Server和Client证书,请保护好keys/ca.key文件。

[root@vpn /etc/openvpn/easy-rsa]# ./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) [Liaoning]:
Locality Name (eg, city) [Shenyang]:
Organization Name (eg, company) [ELM OpenVPN ORG]:
Organizational Unit Name (eg, section) []: OpenVPN Service
Common Name (eg, your name or your server’s hostname) []:OpenVPN Root CA
Email Address [elm@elm.freetcp.com]:

#查看生成的keys

[root@vpn /etc/openvpn/easy-rsa]# ls keys
ca.crt ca.key index.txt serial

#我们可以看到ca.crt ca.key文件已经生成了。
#面我们为服务器生成 Diffie-Hellman 文件
#TLS server 需要使用的一个文件

[root@vpn /etc/openvpn/easy-rsa]# ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
..+……………………………………………………..+……………..
……………………………………………+….+……..+………+…….
………………………………………+.+……………………………..
………………………………………………………………………..
……………………………………..+………………………………..
.+……………………………+………….+……………………………
…………………………………………+…………………………….
…………………+………………………..++*++*++*

#创建并签发VPN Server使用的CA
# `server’ 为创建后的文件名,分别为server.crt server.key

[root@vpn /etc/openvpn/easy-rsa]# ./build-key-server server
Generating a 1024 bit RSA private key
………………….++++++
……………++++++
writing new private key to ‘server.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) [Liaoning]:
Locality Name (eg, city) [Shenyang]:
Organization Name (eg, company) [ELM OpenVPN ORG]:
Organizational Unit Name (eg, section) []:OpenVPN Service
Common Name (eg, your name or your server’s hostname) []:Server No.1
Email Address [elm@elm.freetcp.com]:

Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName :PRINTABLE:’CN’
stateOrProvinceName :PRINTABLE:’Liaoning’
localityName :PRINTABLE:’Shenyang’
organizationName :PRINTABLE:’ELM OpenVPN ORG’
organizationalUnitName:PRINTABLE:’OpenVPN Service’
commonName :PRINTABLE:’Server No.1′
emailAddress :IA5STRING:’elm@elm.freetcp.com’
Certificate is to be certified until Feb 26 14:43:44 2015 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

#为防止恶意攻击(如DOS、UDP port flooding),我们生成一个"HMAC firewall"

[root@vpn /etc/openvpn/easy-rsa]# openvpn –genkey –secret keys/ta.key

#Server使用的配置文件server.conf
—————-CUT Here————-
port 1194
;proto tcp
proto udp
;dev tap
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server 10.8.0.0 255.255.0.0
ifconfig-pool-persist ipp.txt
;client-to-client
;duplicate-cn
keepalive 10 120
tls-auth ta.key 0
plugin ./openvpn-auth-pam.so openvpn
client-cert-not-required
username-as-common-name
comp-lzo
;max-clients 100
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
;log         /var/log/openvpn.log
;log-append  openvpn.log
verb 4
;mute 20
————–Cut Here—————–

;client-to-client #如果让Client之间可以相互看见,去掉本行的注释掉,否则Client之间无法相互访问
;duplicate-cn  #是否允许一个User同时登录多次,去掉本行注释后可以使用同一个用户名登录多次
plugin ./openvpn-auth-pam.so openvpn #说明使用的插件,openvpn为插件的参数,使用pam的servicesname
client-cert-not-required #不请求客户的CA证书,使用User/Pass验证
username-as-common-name #使用客户提供的UserName作为Common Name

把server.conf文件保存到/etc/opennvpn目录中,并把使用easy-rsa下的脚本什成的key都复制到/etc/openvpn目录下,命令如下:  
[root@vpn /etc/openvpn/easy-rsa]# cp keys/ca.crt ../
[root@vpn /etc/openvpn/easy-rsa]# cp keys/server.crt ../
[root@vpn /etc/openvpn/easy-rsa]# cp keys/server.key ../
[root@vpn /etc/openvpn/easy-rsa]# cp keys/dh1024.pem ../
[root@vpn /etc/openvpn/easy-rsa]# cp keys/ta.key ../
[root@vpn /etc/openvpn/easy-rsa]# cp /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so ../

#立即启动openenvpn
[root@vpn /etc/openvpn/easy-rsa]# /etc/init.d/openvpn start

#接下来配置客户端的配置文件client.conf:
#Linux或Unix下使用扩展名为.conf Windows下使用的是.ovpn,并把需要使用的文件复制到配置文件所在目录ca.crt ta.key
————-Cut Here———————
client
;dev tap
dev tun
;proto tcp
proto udp
remote 61.1.1.2 1194
;remote my-server-2 1194
remote-random
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
auth-user-pass
ns-cert-type server
tls-auth ta.key 1
route 192.168.0.0 255.255.252.0
comp-lzo
verb 4
;mute 20
————Cut Here———————–

auth-user-pass #询问用户名和密码

Linux下Client的OpenVPN的安装方法一样,只是配置文件和keys上的不同,只要把client.conf ca.crt ta.key复制到/etc/openvpn目录即可启动VPN。
Win下OpenVPN的安装,WIN下有图形界面的OpenVPN-GUI程序,下载地址http://openvpn.se

这里使用的是TUN设备,主要考虑到Client客户多,VPN的效率和广播的问题,选用TUN设备,因为客户端可能是
Windows系统,Win系统TUN设备获得的IP地址将会是/30的地址,所以有3*Client个地址浪费,所以地址池设置得比较大。

这样你每次使用VPN登录的时候,程序会自动询问你得用户名和密码,输入正确后就可以连接上VPN了,
连接VPN后所有访问内网(192.168.0.0/22)的数据都从VPN经过。
如果Win的Client比较多,可以试着把ca.crt ta.key client.ovpn打包到安装包程序里,具体操作方法参见:

http://openvpn.se/files/howto/openvpn-howto_roll_your_own_installation_package-Rev1.1.html

然后发布改软件包即可,最好小心保管ta.key文件(防止Dos攻击)。

#首先要把系统的Forward打开
[root@vpn /etc]# vi sysctl.conf
修改
# Controls IP packet forwarding
net.ipv4.ip_forward = 1

#IPTABLES的配置文件
[root@vpn /etc/sysconfig]# cat iptables
# Generated by iptables-save v1.2.1a on Tue Nov  6 19:50:51 2001
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -s 192.168.0.0/255.255.252.0 -o eth0 -j SNAT –to-source 61.1.1.2
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:BLOCK – [0:0]
:ANTIVIRUS – [0:0]
# block internal ip address
-A INPUT -i lo -j ACCEPT
-A INPUT -j BLOCK
-A INPUT -j ANTIVIRUS

-A BLOCK -s 192.168.0.0/16 -d 0/0 -j RETURN
-A BLOCK -s 172.16.0.0/12 -d 0/0 -j REJECT
-A BLOCK -s 10.0.0.0/8 -d 0/0 -j RETURN
-A BLOCK -s 127.0.0.0/8 -d 0/0 -j REJECT
-A BLOCK -s 0.0.0.0/8 -d 0/0 -j REJECT
-A BLOCK -s 169.254.0.0/16 -d 0/0 -j REJECT
-A BLOCK -s 192.0.2.0/24 -d 0/0 -j REJECT
-A BLOCK -s 204.152.64.0/23 -d 0/0 -j REJECT
-A BLOCK -s 224.0.0.0/3 -d 0/0 -j REJECT

-A INPUT -p icmp -j ACCEPT

# OSPFD
-A INPUT -d 224.0.0.0/24 -j ACCEPT

# sync time
-A INPUT -p udp -m udp –sport 123 -j ACCEPT

# accept dns
-A INPUT -p udp -m udp –sport 53 -j ACCEPT

# accept ssh from any
-A INPUT -p tcp -m tcp –dport 22 –syn -j ACCEPT

# accept dhcp request
-A INPUT -p udp -m udp –dport 67 -j ACCEPT

# OpenVPN 1194_UDP
-A INPUT -p udp -m udp –dport 1194 -j ACCEPT

# www
-A INPUT -p tcp -m tcp –dport 80 –syn -j ACCEPT

# keep stats
-A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m state –state INVALID -j DROP

# Reject all packet to me
-A INPUT -p tcp -m tcp –syn -j REJECT –reject-with tcp-reset
-A INPUT -p udp -m udp -j REJECT

-A FORWARD -j ANTIVIRUS

-A ANTIVIRUS -p tcp -m tcp –dport 135:139 -j DROP
-A ANTIVIRUS -p tcp -m tcp –dport 445 -j DROP
-A ANTIVIRUS -p udp -m udp –dport 69 -j DROP
-A ANTIVIRUS -p udp -m udp –dport 135:139 -j DROP
-A ANTIVIRUS -p udp -m udp –dport 1434 -j DROP

COMMIT
[root@vpn /etc/sysconfig]#

本文是本人在实验+一字一句的敲上去,如果转载,麻烦注明出处,谢谢