86201746 2019-07-01
OpenVpn + Mysql + Pam插件
虚拟专用网VPN(virt ual private network)是在公共网络中建立的安全网络连接,这个网络连接和普通意义上的网络连接不同之处在于,它采用了专有的隧道协议,实现了数据的加密和完整性的检验、用户的身份认证,从而保证了信息在传输中不被偷看、篡改、复制,从网络连接的安全性角度来看,就类似于再公共网络中建立了一个专线网络一样,只补过这个专线网络是逻辑上的而不是物理的所以称为虚拟专用网。通过OpenVpn实现隧道的建立,Mysql+Pam_Mysql插件实现用户名密码验登录,实现多用户配置登录配置。去除一对一生成认证文件的繁琐操作。
OpenVpn的安装需要tun模块的支持,命令如下:
$ ls mod | grep tun # 查看系统是否支持tun模块 $ modinfo tun # 查看模块信息 $ /etc/init.d/iptables # 查看iptables是否存在
$ yum install openssl-devel openssl gcc gcc-c++ cmake -y
$ vim /etc/profile net.ipv4.ip_forward = 0 # 修改为 net.ipv4.ip_forward = 1 $ sysctl -p # 使配置生效
下载地址:openvpn-2.4.6.tar.gz
LZO 是致力于解压速度的一种数据压缩算法,LZO 是 Lempel-Ziv-Oberhumer 的缩写。这个算法是无损算法,参考实现程序是线程安全的。
实现它的一个自由软件工具是lzop。最初的库是用 ANSI C 编写、并且遵从 GNU通用公共许可证发布的。现在 LZO 有用于 Perl、Python 以及 Java 的各种版本。代码版权的所有者是 Markus F. X. J. Oberhumer。
LZO 库实现了许多有下述特点的算法:
• 解压简单,速度非常快。 • 解压不需要内存。 • 压缩相当地快。 • 压缩需要 64 kB 的内存。 • 允许在压缩部分以损失压缩速度为代价提高压缩率,解压速度不会降低。 • 包括生成预先压缩数据的压缩级别,这样可以得到相当有竞争力的压缩比。 • 另外还有一个只需要 8 kB 内存的压缩级别。 • 算法是线程安全的。 • 算法是无损的。
下载地址:lzo-2.10.tar.gz
$ mkdir -p /usr/src/software $ cd /usr/src/software $ wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz $ tar -xzvf lzo-2.10.tar.gz $ cd /usr/src/software/lzo-2.0 $ ./configure --prefix=/usr/local/lzo # 指定安装目录 $ make # 编译 $ make check # 编译检查 $ make install # 安装
$ cd /usr/src/software $ tar -xzvf openvpn-2.4.6.tar.gz $ cd openvpn-2.4.6 $ ./configure ---------- # 执行以上命令之后,安装报错: #checking for lz4.h... no #usable LZ4 library or header not found, using version in src/compat/compat-lz4.* #checking git checkout... no #configure: error: lzo enabled but missing $ yum -y install lzo-devel ---------- #又报错: #usable LZ4 library or header not found, using version in src/compat/compat-lz4.* #checking git checkout... no #checking whether the compiler acceppts -Wno-unused-function... yes #checking whether the compiler acceppts -Wno-unused-parameter... yes #checking whether the compiler acceppts -Wall... yes #configure: error: libpam required but missing $ yum -y install pam-devel $ ./configure ---------- \\以下为配置的输出内容 checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu checking for style of include used by make... GNU checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking whether gcc understands -c and -o together... yes checking dependency style of gcc... gcc3 checking how to run the C preprocessor... gcc -E ............\\Openssl版本最好在安装之前进行下升级,版本至少是0.9.6 checking whether TUNSETPERSIST is declared... yes checking for setcon in -lselinux... yes checking for pam_start in -lpam... yes checking for PKCS11_HELPER... no checking for OPENSSL... yes checking for SSL_CTX_new... yes checking for EVP_CIPHER_CTX_set_key_length... yes checking for ENGINE_load_builtin_engines... yes checking for ENGINE_register_all_complete... yes checking for ENGINE_cleanup... yes ............\\检查lzo文件,如果这边没有通过,则无法安装OpenVpn checking for lzo1x_1_15_compress in -llzo2... yes checking lzo/lzoutil.h usability... yes checking lzo/lzoutil.h presence... yes checking for lzo/lzoutil.h... yes checking lzo/lzo1x.h usability... yes checking lzo/lzo1x.h presence... yes checking for lzo/lzo1x.h... yes ............\\最后一段输出 checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating version.sh config.status: creating Makefile config.status: creating build/Makefile config.status: creating build/msvc/Makefile config.status: creating build/msvc/msvc-generate/Makefile config.status: creating distro/Makefile config.status: creating distro/rpm/Makefile config.status: creating distro/rpm/openvpn.spec config.status: creating distro/systemd/Makefile config.status: creating include/Makefile config.status: creating src/Makefile config.status: creating src/compat/Makefile config.status: creating src/openvpn/Makefile config.status: creating src/openvpnserv/Makefile config.status: creating src/plugins/Makefile config.status: creating src/plugins/auth-pam/Makefile config.status: creating src/plugins/down-root/Makefile config.status: creating tests/Makefile config.status: creating tests/unit_tests/Makefile config.status: creating tests/unit_tests/example_test/Makefile config.status: creating tests/unit_tests/openvpn/Makefile config.status: creating tests/unit_tests/plugins/Makefile config.status: creating tests/unit_tests/plugins/auth-pam/Makefile config.status: creating vendor/Makefile config.status: creating sample/Makefile config.status: creating doc/Makefile config.status: creating tests/t_client.sh config.status: creating config.h config.status: config.h is unchanged config.status: creating include/openvpn-plugin.h config.status: include/openvpn-plugin.h is unchanged config.status: executing depfiles commands config.status: executing libtool commands ---------- $ echo $? 0 $ make # 编译 $ make install # 最后一步,安装 \\最后几行输出 # /bin/mkdir -p '/usr/local/share/doc/openvpn' # /usr/bin/install -c -m 644 README README.IPv6 README.mbedtls Changes.rst COPYRIGHT.GPL COPYING '/usr/local/share/doc/openvpn' #make[3]: Leaving directory `/usr/src/software/openvpn-2.4.6' #make[2]: Leaving directory `/usr/src/software/openvpn-2.4.6' #make[1]: Leaving directory `/usr/src/software/openvpn-2.4.6'
下载地址: easy-rsa-3.0.5.zip
$ unzip easy-rsa-3.0.5.zip $ mv easy-rsa-3.0.5 openvpn-2.4.6 $ /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3 # 进入目录 $ cp vars.example vars # 一般情况下,默认的配置文件可以满足需求,也可以根据需要修改 $ vim vars # 修改以下内容 ———————————开始——————————— set_var EASYRSA "`pwd`" set_var EASYRSA_OPENSSL "openssl" set_var EASYRSA_OPENSSL "openssl" set_var EASYRSA_REQ_COUNTRY "CN" set_var EASYRSA_REQ_PROVINCE "Beijing" set_var EASYRSA_REQ_CITY "Chaoyang" set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" set_var EASYRSA_REQ_EMAIL "[email protected]" set_var EASYRSA_REQ_OU "My Organizational Unit" set_var EASYRSA_KEY_SIZE 2048 # In how many days should the root CA key expire? set_var EASYRSA_CA_EXPIRE 3650 # In how many days should certificates expire? set_var EASYRSA_CERT_EXPIRE 3650 ———————————结束———————————
$ pwd /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3 $ ./easyrsa init-pki # 建立一个空的pki结构,生成一系列的文件和目录 # 初始化,会在当前目录创建PKI目录,用于存储一些中间变量及最终生成的证书 Note: using Easy-RSA configuration from: ./vars init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3/pki $ ./easyrsa build-ca # 创建根证书ca 密码 和 cn需要记住 # 创建根证书,首先会提示设置密码,用于ca对之后生成的server和client证书签名时使用,然后会提示设置Country Name,State or Province Name,Locality Name,Organization Name,Organizational Unit Name,Common Name,Email Address,可以键入回车使用默认的,也可以手动更改 Note: using Easy-RSA configuration from: ./vars Enter New CA Key Passphrase: #123456 Re-Enter New CA Key Passphrase: #123456 #此密码需要记住,后续还会使用 Generating RSA private key, 2048 bit long modulus .................................................................................................................................................................................................+++ ..............................................................................................................+++ e is 65537 (0x10001) 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. ----- Common Name (eg: your user, host, or server name) [Easy-RSA CA]: #mycompany CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3/pki/ca.crt $ ./easyrsa gen-req server nopass # 创建服务端证书 common name 最好不要跟前面的cn那么一样 # 创建server端证书和private key,nopass表示不加密private key,然后会提示设置Country Name,State or Province Name,Locality Name,Organization Name,Organizational Unit Name,Common Name,Email Address,可以键入回车使用默认的,也可以手动更改 Note: using Easy-RSA configuration from: ./vars Generating a 2048 bit RSA private key ...............+++ ..................................+++ writing new private key to '/usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3/pki/private/server.key.Yv4YWmpFoG' ----- 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. ----- Common Name (eg: your user, host, or server name) [server]: #original Keypair and certificate request completed. Your files are: req: /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3/pki/reqs/server.req key: /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3/pki/private/server.key
签约服务端证书
$ ./easyrsa sign server server # 签约服务端证书 # 给server端证书做签名,首先是对一些信息的确认,可以输入yes,然后输入build-ca时设置的那个密码 $ ./easyrsa gen-dh # 创建Diffie-Hellman # 创建Diffie-Hellman,时间会有点长,耐心等待 Note: using Easy-RSA configuration from: ./vars Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time .....................+.................................................................................. ..+.................+..................................................++*++* DH parameters of size 2048 created at /usr/src/software/openvpn-2.4.6/easy-rsa-3.0.5/easyrsa3/pki/dh.pem
# 创建client端证书,需要单独把easyrsa3文件夹拷贝出来一份,删除里面的PKI目录,然后进入到此目录 $ cd ~ $ mkdir client && cd client $ cp -R /usr/src/software/easy-rsa-3.0.5 ./ $ cd easy-ras-3.0.5/easyrsa3 $ cp vars.example vars # 开始生成 $ ./easyrsa init-pki # 初始化,会在当前目录创建PKI目录,用于存储一些中间变量及最终生成的证书 $ ./easyrsa gen-req liuxy \\用自己的名字,需要创建一个密码 和 cn name,自己用的 需要记住 Note: using Easy-RSA configuration from: ./vars Generating a 2048 bit RSA private key .......+++ ....................................................................+++ writing new private key to '/root/client/easy-rsa-3.0.5/easyrsa3/pki/private/liuxy.key.hweu50ee1N' Enter PEM pass phrase: \\445566 Verifying - Enter PEM pass phrase: \\445566 #需要记住,可能连接的时候会用 ----- 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. ----- Common Name (eg: your user, host, or server name) [liuxy]: \\niklaus Keypair and certificate request completed. Your files are: req: /root/client/easy-rsa-3.0.5/easyrsa3/pki/reqs/liuxy.req key: /root/client/easy-rsa-3.0.5/easyrsa3/pki/private/liuxy.key
至此,客户端的证书已经成功生成,后续步骤需要签约
客户端签约
$ cd /usr/src/software/openvpn-2.4.6 $ mv easy-rsa-3.0.5/ /etc/openvpn/ $ cp sample/sample-config-files/server.conf /etc/openvpn/ $ ./easyrsa import-req ~/client/easy-rsa-3.0.5/easyrsa3/pki/reqs/liuxy.req liuxy \\导入req # Note: using Easy-RSA configuration from: ./vars # The request has been successfully imported with a short name of: liuxy # You may now use this name to perform signing operations on this request. $ ./easyrsa sign client liuxy \\用户签约,根据提示输入服务端的ca密码 Note: using Easy-RSA configuration from: ./vars You are about to sign the following certificate. Please check over the details shown below for accuracy. Note that this request has not been cryptographically verified. Please be sure it came from a trusted source or that you have verified the request checksum with the sender. Request subject, to be signed as a client certificate for 3650 days: subject= commonName = niklaus Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes Using configuration from /etc/openvpn/easy-rsa-3.0.5/easyrsa3/openssl-easyrsa.cnf Enter pass phrase for /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/private/ca.key: \\123456 Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows commonName :PRINTABLE:'niklaus' Certificate is to be certified until Jun 26 15:03:54 2028 GMT (3650 days) Write out database with 1 new entries Data Base Updated Certificate created at: /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/issued/liuxy.crt
$ tree pki pki ├── ca.crt ├── certs_by_serial │ ├── 0576F004D6ECB014B5C946C05DC88173.pem │ └── 62014DDC889192A89E19F517AE73546C.pem ├── dh.pem ├── index.txt ├── index.txt.attr ├── index.txt.attr.old ├── index.txt.old ├── issued │ ├── liuxy.crt │ └── server.crt ├── private │ ├── ca.key │ └── server.key ├── reqs │ ├── liuxy.req │ └── server.req ├── serial └── serial.old * 客户端 $ tree pki pki ├── private │ └── liuxy.key └── reqs └── liuxy.req
把证书文件放到统一目录下,方便查找
服务端证书$ cp /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/ca.crt /etc/openvpn/ $ cp /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/private/server.key /etc/openvpn/ $ cp /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/issued/server.crt /etc/openvpn/ $ cp /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/dh.pem /etc/openvpn/客户端证书
$ mkdir /liuxy/client $ cp /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/ca.crt /liuxy/client/ $ cp /etc/openvpn/easy-rsa-3.0.5/easyrsa3/pki/issued/liuxy.crt /liuxy/client/ $ cp ~/client/easy-rsa-3.0.5/easyrsa3/pki/private/liuxy.key /liuxy/client/
至此,证书安装、生成、认证完成 !
注意:生成客户端证书步骤可忽略,因为在openvpn+mysql+pam插件认证的环境下,是不需要配置一对一客户端证书的。$ cd /etc/openvpn/ $ cp server.conf server.conf.original $ vim server.conf
** 服务端配置文件见最后,因为中间出现过好多报错
$ /usr/local/sbin/openvpn --daemon --config /etc/openvpn/server.conf & # 启动 $ tail -f openvpn.log #Fri Jun 29 16:21:58 2018 Could not determine IPv4/IPv6 protocol. Using AF_INET #Fri Jun 29 16:21:58 2018 Socket Buffers: R=[87380->87380] S=[16384->16384] #Fri Jun 29 16:21:58 2018 Listening for incoming TCP connection on [AF_INET][undef]:11194 #Fri Jun 29 16:21:58 2018 TCPv4_SERVER link local (bound): [AF_INET][undef]:11194 #Fri Jun 29 16:21:58 2018 TCPv4_SERVER link remote: [AF_UNSPEC] #Fri Jun 29 16:21:58 2018 MULTI: multi_init called, r=256 v=256 #Fri Jun 29 16:21:58 2018 IFCONFIG POOL: base=10.8.0.4 size=62, ipv6=0 #Fri Jun 29 16:21:58 2018 IFCONFIG POOL LIST #Fri Jun 29 16:21:58 2018 MULTI: TCP INIT maxclients=100 maxevents=104 #Fri Jun 29 16:21:58 2018 Initialization Sequence CompletedOpenVpn能成功启动,说明已经配置成功。如果有报错信息,可根据日志查看解决。
$ yum -y install epel-release $ yum install -y mysql mysql-devel mysql-server $ yum install -y pam_krb5 pam_mysql pam pam-devel $ yum install -y cyrus-sasl cyrus-sasl-plain cyrus-sasl-devel cyrus-sasl-lib cyrus-sasl-gssapi $ service mysqld start $ mysql > create database vpn; > grant all privileges on vpn.* to 'vpn'@'localhost' identified by '111213'; > grant all privileges on vpn.* to 'vpn'@'%' identified by '111213'; > flush privileges; > CREATE TABLE vpnuser ( name char(20) NOT NULL, password char(128) default NULL, active int(10) NOT NULL DEFAULT 1, PRIMARY KEY (name) ); $ update mysql.user set password=PASSWORD('111213') where user='root'; # 为root用户添加密码,增加安全性Mysql数据库创建OpenVpn使用的表和用户,为保证服务的连通性,请确保Vpn连接账户的权限为可执行。
下载地址:openvpn-2.0.9.tar.gz
$ pwd /usr/src/software/openvpn-2.0.9/plugin/auth-pam $ make将生成的openvpn-auth-pam.so文件复制到/etc/openvpn/目录下
配置Pam_mysql模块
手动创建/etc/pam.d/openvpn文件$ vim /etc/pam.d/openvpn auth sufficient pam_mysql.so user=vpn passwd=caiyu111213 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=caiyu111213 host=localhost db=vpn table=vpnuser usercolumn=name passwdcolumn=password where=active=1 sqllog=0 crypt=2
测试认证
进行插件的测试认证之前,请确定已经配置好配置文件,并且已经重新启动服务。有时候出现问题就可能是因为服务修改配置后没有重启导致。$ testsaslauthd -u liuxy -p 111213 -s openvpn 0: OK "Success."出现OK说明认证成功
OpenVpn配置文件添加认证模块
认证模块配置没问题之后,需要在openvpn配置文件中添加模块调用,如下:client-cert-not-required plugin /etc/openvpn/openvpn-auth-pam.so openvpn
$ cat /etc/openvpn/server.conf | grep -v "^#" local a.b.c.d port 11194 proto tcp ;proto udp ;dev tap dev tun ;dev-node MyTap ca /etc/openvpn/ca.crt cert /etc/openvpn/server.crt key /etc/openvpn/server.key # This file should be kept secret dh /etc/openvpn/dh.pem ;topology subnet server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt ;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100 ;server-bridge ;push "route 192.168.10.0 255.255.255.0" ;push "route 192.168.20.0 255.255.255.0" push "route 172.16.16.0 255.255.255.0" push "route 172.16.16.10 255.255.255.255" push "route 172.16.16.11 255.255.255.255" push "route 172.16.16.12 255.255.255.255" ;client-config-dir ccd ;route 192.168.40.128 255.255.255.248 ;client-config-dir ccd ;route 10.9.0.0 255.255.255.252 ;learn-address ./script ;push "redirect-gateway def1 bypass-dhcp" ;push "dhcp-option DNS 208.67.222.222" ;push "dhcp-option DNS 208.67.220.220" client-to-client duplicate-cn keepalive 10 120 ;tls-auth ta.key 0 # This file is secret ;cipher AES-256-CBC ;compress lz4-v2 ;push "compress lz4-v2" comp-lzo max-clients 100 ;user nobody ;group nobody persist-key persist-tun status /etc/openvpn/openvpn-status.log log /etc/openvpn/openvpn.log log-append /etc/openvpn/openvpn.log verb 3 ;mute 20 ;explicit-exit-notify 1 client-cert-not-required plugin /etc/openvpn/openvpn-auth-pam.so openvpn
客户端只需要2个文件:
$ cat client.ovpn | grep -v "^#" client ;dev tap dev tun ;dev-node MyTap proto tcp ;proto udp remote xxx.xxx.xxx.xxx 11194 # 此处配置公司局域网外网IP地址或者域名地址用于连接到局域网 ;remote my-server-2 1194 ;remote-random resolv-retry infinite ;user nobody ;group nobody persist-key persist-tun ;http-proxy-retry # retry on connection failures ;http-proxy [proxy server] [proxy port #] ;mute-replay-warnings ca ca.crt auth-user-pass ns-cert-type server ;tls-auth ta.key 1 ;cipher x comp-lzo verb 3 ;mute 20
配置文件每一项的具体意义都必须清楚,才能配置正确
针对这种情况,可以提供两种方法使用:
SSH链路转发方式,是通过指定外网服务器的固定IP来添加端口转发,实现端口映射。具体命令格式如下:
ssh -C -f -N -g -R 11194:内网IP:11193 root@外网IP地址 -o ServerAliveInterval=360 -o ServerAliveCountMax=5000 # 尽量不要使用root账户通过端口映射成功连接到内网OpenVpn服务器之后,无法ping通内网其他服务器怎么办。还需要在openvpn服务器添加地址转发,从而通过客户端连接后,打通内网(局域网内)所有机器,iptables命令如下:
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
各种方面都要考虑,其实比较有意思,哈哈