Open×××的工作原理

        虚拟网卡在Linux2.4版本以上,操作系统开始支持一个名为tun的设备,tun设备的驱动程序中包含两个部分,一部分是字符设备驱动,一部分是网卡驱动。网卡驱动把从TCP/IP协议栈收到的数据包结构skb放于tun设备的读取队列,用户进程通过调用字符设备接口read获取完整的IP数据包,字符驱动read函数的功能是从设备的读取队列读取数据,将核心态的skb传递给用户;反过来字符驱动设备write函数给用户提供了把用户态的数据写入核心态的接口,write函数把用户数据写入核心空间并穿入TCP/IP协议栈。该设备既能以字符设备的方式被读写,作为系统的虚拟网卡,也具有和物理网卡相同的特点:能够配置IP地址和路由。对虚拟网卡的使用是Open×××实现其SSL ×××功能的关键
地址池以及路由Open×××服务器一般需要配置一个虚拟IP地址池和一个自用的静态虚拟IP地址(静态地址和地址池必须在同一个子网中),然后为每一个成功建立SSL连接的客户端动态分配一个虚拟IP地址池中未分配的地址。这样,物理网络中的客户端和Open×××服务器就连接成一个虚拟网络上的星型结构局域网,Open×××服务器成为每个客户端在虚拟网络上的网关。Open×××服务器同时提供对虚拟网卡的路由管理。当客户端对Open×××服务器后端的应用服务器任何访问时,数据包都会经过路由流经虚拟网卡,Open×××程序在虚拟网卡上获取数据IP报文,然后使用SSL协议将这些IP报文封装起来,再经过物理网卡发送出去。Open×××的服务器和客户端在虚拟网卡之上建立起来一个虚拟的局域网网络,这个虚拟的局域网络对系统的用户来说是透明的。
        客户端与服务端安全连接的建立Open×××的服务器和客户端支持tcp和udp两种连接方式,只需要在服务端和客户端预先定义好使用的连接方式(tcp或udp)和端口号,客户端和服务端在这个连接的基础上进行SSL握手。连接包括SSL的握手以及虚拟网络上的管理信息,Open×××将虚拟网上的网段、地址、路由发送给客户端。连接成功后,客户端和服务端建立起SSL安全连接,客户端和服务端的数据都流入虚拟网卡做SSL的处理,再在tcp或udp的连接上从物理网卡发送出去。

数据包的处理过程

发送数据流程

         应用层的外出数据,经过系统调用接口传入核心TCP/IP层做处理,在TCP/IP经过路由到虚拟网卡,虚拟网卡的网卡驱动发送处理程序hard_start_xmit()将数据包加入skb表并完成数据包从核心区到用户区的复制,Open×××调用虚拟网卡的字符处理程序tun_read(),读取到设备上的数据包,对读取的数据包使用SSL协议做封装处理后,通过socket系统调用发送出去。

接收数据流程

         物理网卡接收数据包,经过核心的TCP/IP上传到Open×××,Open×××通过link_socket_read()接收数据包,使用SSL协议进行解包处理,经过处理的数据包Open×××调用虚拟网卡的字符处理程序tun_write()写入虚拟网卡的字符设备,设备驱动程序完成数据从用户区到核心区的复制,并将数据写入skb链表,然后调用网卡netif_rx()接收程序,数据包再次进入系统TCP/IP协议栈,传到上层应用程序。

20170210171516153


一、服务端安装和配置

1、安装依赖包

 yum -y install openssl openssl-devel lzo open*** easy-rsa


2、修改信息文件

  修改注册信息

  cd /usr/share/easy-rsa/2.0/


  vim vars

  export KEY_COUNTRY="CN"  //国家

  export KEY_PROVINCE="Guangdong" //省

  export KEY_CITY="Shenzhen" //市

  export KEY_ORG="Fort-Funston"  //组织

  export KEY_EMAIL="me@myhost.mydomain"  //邮箱

  export KEY_OU="MyOrganizationalUnit"  //部门


3、初始化环境

  source vars

  ./clean-all


4、生成根证书

  ./build-ca


5、服务端生成证书和密钥

  ./build-key-server server  //一直回车,直到提示y/n


6、为客户端生成证书和密钥

  ./build-key liuly  //一直回车,直到提示y/n


7、创建dh文件

  ./build-dh //生成dh2048.pem


8、生成ta.key文件

  open*** --genkey --secret keys/ta.key //防DDoS***、UDP淹没等恶意***


9、创建服务器配置文件

  将需要用到的open***证书和密钥复制一份到/etc/open***/

  cp /usr/share/easy-rsa/2.0/keys/{ca.crt,server.{crt,key},dh2048.pem,ta.key} /etc/open***/


  编辑配置文件

  cp /usr/share/doc/open***-2.3.11/sample/sample-config-files/server.conf /etc/open***/

  vim server.conf

  port 1194

  proto tcp

  dev tun

  ca ca.crt

  cert server.crt

  key server.key  # This file should be kept secret

  dh dh2048.pem

  server 10.8.0.0 255.255.255.0 //默认虚拟局域网网段,不要和实际的局域网冲突即可

  push "route 192.168.224.0 255.255.255.0"

  ifconfig-pool-persist ipp.txt

  duplicate-cn //如果客户端都使用相同的证书和密钥连接×××,一定要打开这个选项,否则每个证书只允许一个人连接×××

  #client-to-client  //可以让客户端之间相互访问直接通过open***程序转发,根据需要设置

  keepalive 10 120

  tls-auth keys/ta.key 0

  comp-lzo

  persist-key

  persist-tun

  status open***-status.log

  verb 5

  auth-user-pass-verify /etc/open***/checkpsw.sh via-env
  client-cert-not-required //代表只使用用户名密码方式验证登录,如果不加,则代表需要证书和用户名密码双重验证登录

  username-as-common-name


vim /etc/open***/checkpsw.sh

#!/bin/bash

PASSFILE="/etc/open***/psw_file"

LOG_FILE="/var/log/open***_psw.log"

TIME_STAMP=`date "+%F %T"`



if [ ! -r "${PASSFILE}" ]; then

    echo "${TIME_STAMP}: Could not open password file \"${PASSFILE}\" for reading." >> ${LOG_FILE}

    exit 1

fi


CORRECT_PASSWORD=`awk '!/^;/&&!/^#/&&$1=="'${username}'"{print $2;exit}' ${PASSFILE}`


if [ "${CORRECT_PASSWORD}" = "" ]; then 

    echo "${TIME_STAMP}: User does not exist: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}

    exit 1

fi


if [ "${password}" = "${CORRECT_PASSWORD}" ]; then 

    echo "${TIME_STAMP}: Successful authentication: username=\"${username}\"." >> ${LOG_FILE}

    exit 0

fi


echo "${TIME_STAMP}: Incorrect password: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}

exit 1


vim /etc/open***/psw_file

liuly 123456


10、配置内核,开启防火墙,启动服务

  sed -i '/net.ipv4.ip_forward/s/0/1/' /etc/sysctl.conf

  sysctl -p


  iptables -I INPUT -p tcp --dport 1194 -m comment --comment "open***" -j ACCEPT

  iptables -t nat -A nat -A POSTROUTING -s 192.168.224.0/24 -j MASQUERADE

  service iptables save


  service open*** save

  chkconfig open*** on


11、创建客户端配置文件

  cp /usr/share/doc/open***-2.3.11/sample/sample-config-files/client.conf /etc/open***/

  vim client.conf

  client

  dev tun

  proto tcp

  remote 192.168.224.2 1194  //open***服务的ip和port

  resolv-retry infinite

  nobind

  persist-key

  persist-tun

  ca ca.crt

  cert liuly.crt

  key liuly.key

  #remote-cert-tls server

  ns-cert-type server

  tls-auth ta.key 1

  comp-lzo

  verb 3

  auth-user-pass


二、windows客户端安装及配置

win7 64位

http://swupdate.open***.org/community/releases/open***-install-2.3.3-I002-x86_64.exe


将open***服务器上的client.conf ca.crt liuly.crt liuly.key ta.key上传到win客户端安装目录下

D:\Program Files\Open×××\config


现在就可以启动客户端open***啦



PS:

1、生成密钥

openssl genrsa -out private.key 1024

openssl rsa -in private.key -pubout -out pub.key

chmod 600 pub.key private.key


2、加密

echo "aaa aaa"|openssl rsautl -encrypt -inkey pub.key -pubin >> psw

chmod 400 psw

3、解密

cat paw|openssl rsautl -decrypt -inkey private.key

aaa aaa


4、后续增加新用户脚本:

#!/bin/bash

users_num="$#"

users="$@"

work_dir="/usr/share/easy-rsa/2.0/"



[ $uses_num -ne 1 ] && { 

    echo "$0 user1 [ user2 ... ]"

    exit 1

}


add_user(){

    cd $work_dir

    source ./vars

    for _user in $users; do

        mkdir -p "$HOME/client/$_user"

        expect -c "

        spawn ./build-key $_user

        set timeout 5

        expect {

            \"y/n]\"    {send \"y\r\";exp_continue}

            \"]:\"      {send \"\r\";exp_continue}

        }

        "

        cd keys

        cp ca.crt $_user.crt $_user.key \

            /etc/open***/ta.key  /etc/open***/client.conf \

            "$HOME/client/$_user" -f

        sed -i "/^cert /s/liuly/$_user/" "$HOME/client/$_user/client.conf"

        sed -i "/^key /s/liuly/$_user/" "$HOME/client/$_user/client.conf"

        _passwd="`cat /dev/urandom | sed 's/[^a-zA-Z0-9]//g'  |strings -n 10|head -n 1`"

        echo "$_user $_passwd" >> psw_file        

        cp psw_file /etc/open***/ -f

    done 

}


add_user

5.删除用户

#!/bin/bash

__vars_len="$#"

__vars="$@"


revoke_scripte_dir="$HOME/***/easy-rsa/"

old_dir="$PWD"


[ $__vars_len -ne 1 ] && {

    echo "$0 user1 [ user2 ... ]"

    exit 1

}


[ ! -x "$revoke_scripte_dir/revoke-full" ] && {

    echo "revoke-full script do not exist or can not excute."

    exit 1

}


del_psw_file_user(){

    for user in $__vars; do

        sed -i "/$user/d" psw_file

    done


    [ ! -e "private.key" -a ! -e "pub.key" ] && {

        echo "encrypted key missing. Please generate them first, \

and don't forget copy private.key to /etc/open***"

        exit 1

    }

    sh encry_psw_file.sh

    cp psw /etc/open*** -f

}


revoke_user_rst(){

    cd $revoke_scripte_dir

    source ./vars

    for user in $__vars; do

        ./revoke-full $user

    done

    cp keys/crl.pem /etc/open*** -f

    chmod 400 /etc/open***/crl.pem

    cd $old_dir

}


del_psw_file_user

revoke_user_rst