Yuan Yijun (bbbush) wrote,
Yuan Yijun
bbbush

zz:自动vpn配置详细方案与配置


发信人: bash (bash), 信区: LinuxUnix
标  题: [转载] 自动vpn配置详细方案与配置
发信站: 南京大学小百合站 (Sat Dec  1 02:26:20 2007)

【 以下文字转载自 bash 的blog 】
【 原文由 bash 所发表 】

难得写点本版的长篇的大论的原创,ms上回的那个问题已经有人有解决方案了,
不过我还是把我的解决方案详细写一下,估计也不会那么垃圾,因为我目前还
没有看到网上有类似的这么完整的攻略,试图说清楚整个思路以及实现方法,
所以多少对初学者应该有些意义,虽然每一步都很非常简单,但是如果你能有耐
心看完的话,也许会发现里面包含了有些比较好玩的东西。


首先我声明自己其实是个网络盲,所以行文过程中有什么问题的,希望板油
们批评指正,但是尽量不要用蔑视或者攻击性的词语(用了也无所谓,大不
了我以后不发类似的文章就是了,写起来还是挺累的,哈哈~~)


本文大致分四个部分,第一是问题描述,说明一下我的网络的情况;其次是
我的需求,再次是方案的总体思路,最后是具体的每个环节的实现和配置细
节。

1.问题描述
  
我的网络环境见上图(抱歉原本想贴文本图的,可惜好像小百合上对不齐,
所以只能截图了)。公司这边我的主机名叫dell,其中两个网卡,eth2连的是
我私人的内网192.168.0.0, eth3连的是公司的内网192.168.1.0,两块网
卡的ip分别是192.168.0.3和192.168.1.0。公司的内网通过一个防火墙进
入公网,共享一个公网ip。家里主机名(zealix),一个网卡eth1连的
家里的内网192.168.2.0,eth1地址是192.168.2.1。一个电信ADSL接口,
ppp0,在拨上去的时候分配动态公网ip。限时上网,2Mbps。
我另外一个笔记本,可能随时接在公司使用和家里使用,即接在
192.168.0.0或者192.168.2.0的内网中。
另外,
192.168.0.0的网关 eth2@dell -- 192.168.0.3
192.168.2.0的网关 eth1@zealix ---- 192.168.2.1
192.168.1.0的网关 192.168.1.1




2. 需求分析
我对我网络的需求包含以下内容:
a). 由于我的ADSL是限时的,我希望家里的机器是在我希望的时候上网,
不需要的时候下线。

b). 在任何一个能接触到网络的地方,我想知道当前家里ADSL(ppp0)的
公网地址

c). 我希望任何时候在家里能够随意在ip层访问任何一台在公司内网
(192.168.0.0,192.168.1.0)里面的任何一台机器,包括dell本身

d). 在公司的时候,我希望192.168.0.0中的机器(包括dell)能够在
ip层访问家里的机器zealix包括192.168.2.0中的机器。

e). 我不希望192.168.1.0里面的机器访问我家里的机器,因为混杂了
windows的网络可能会有一些垃圾流量,我不希望它走我可怜的ADSL线路




3. 方案的总体思路
需求a)的满足是通过邮件控制家里的机器,往固定的邮箱发固定的信,
家里的机器通过解析你对它的命令。机器的行为是每隔一段时间上线,
接收邮件,解析命令,如果你对它发出了持续在线的指令,它就持续在线,
否则一分钟以内断线。持续在线期间,如果你对它发出了断线的指令,
它就立马断线。

需求b)的满足是通过udev截获ppp0出现的时间,如果ppp0出现,则发
送包含动态ip的邮件到你的固定邮箱。花生壳是另外一个可能的选择,
但是我不是很信任它(天知道它出了ip以外有没有干其它事情?),
另外,我也不想将我的私人ip长时间公布在某个地方。

需求c),d), e)的满足是让dell时刻监控邮箱,获取最新的zealix的
动态ip,更新自己的静态域名 /etc/hosts, 并试图自动连接zealix,
通过ssh建立VPN,配置两边机器的静态路由,来达到互访的效果。






4. 具体实现细节(包含在不同需求下面可能的变通方式)
这个部分的有些具体的工具是我的选择,每个人可有其它的选择,
至要能达到同等的功能就可

i) 主机上的邮件控制命令
格式:MAIL_CMDS_hostname_command
其中MAIL_CMDS_是魔数,这样整条命令可以用一个grep出来,
hostname指的目标机器,目前只有zealix响应,你想扩展很容易。
command,目前两个:NET_STICK和NET_NOSTICK,分别让主机
持续在线和非持续上线,要扩展也非常容易,有点想法的同志可以
通过这个思路用手机邮件给远程的主机发送任何的脚本命令,
在让命令的结果邮件返回 :)


ii) zealix主机的配置
主要任务:
    *实时邮件发送动态ip信息
    *定时上线接收并分析邮件命令
    *根据邮件命令结果决定是否持续在线还是定时下线
    *内核需要 tun/tap支持,不知道怎么办的参考 http://www.kroah.com/lkn/
    

/etc/hosts内容:
127.0.0.1       localhost
192.168.2.2     ibm-home
192.168.0.2     ibm
192.168.0.3     dell
10.0.0.2        zealix-tun
10.0.0.1        dell-tun
192.168.1.68    dell-soft





sshd 配置:/etc/ssh/sshd_config
关键的几个选项
RSAAuthentication yes
PubkeyAuthentication yes
PermitRootLogin yes
StrictModes yes
ClientAliveInterval 20
PermitTunnel yes


ssh的主要配置:/etc/ssh/ssh_config
    ConnectTimeout 15
    ServerAliveInterval 15
    Tunnel yes
    TunnelDevice 2:2

ssh公钥认证登录配置
root@zealix# ssh-keygen -t rsa
连续回车
取出公钥 .ssh/id_rsa.pub 任何方式传送到dell上,
root@dell# cat id_rsa.pub >> .ssh/authorized_keys2
类似方式将root@dell的公钥添加到root@zealix里面


udev配置: 
/etc/udev/rules.d/  下面添加一个规则文件如 z100_ppp_ip_letter.rules
内容为
ACTION=="add", SUBSYSTEM=="net", KERNEL=="ppp[0-9]",   \
RUN+="/home/xianai/ppp-address.sh"
------------- ppp-address.sh -------------------------------------------------
------
#!/bin/bash
FROM="none"
TO="yourname@yourisp.com"  #
CC=""
BCC=""
SUBJECT="Today's PPP address"
sleep 10s

MESSAGE=`/sbin/ifconfig ppp0 | /bin/sed -e '/P-t-P/!d'  \
-e 's/^[[:space:]]* inet addr://g' -e 's/[[:space:]]*P-t-P:.*Mask:.*$//g'`

ATTACHMENT="[] []"
echo "$MESSAGE" | /usr/bin/mail -s "$SUBJECT" -c "$CC" -b "$BCC" "$TO"
------------  ppp-address.sh END ---------------------------------------------

ppp-address.sh里面对应的字段自己填,sleep 10s不要删!udev触发的实时性很高,
必须等待一小段时间才能100%保证ppp0的ip能在用户层被探测到


邮件系统的配置 
    发送邮件:exim4 + smtp.gmail.com
        配置参考链接 http://wiki.debian.org/GmailAndExim4 

    收邮件和过滤邮件:kmail
        收邮件:略(你还没傻吧)
        邮件过滤: Settings ==> config filters ==> filter actions
                    Pipe through: /home/xianai/kmail_filter_mailcmds.sh
                    其它相应的过滤匹配条件自己填。
                    
---------kmail_filter_mailcmds.sh----------------------------------------
#!/bin/bash
grep MAIL_CMDS_zealix | sed -e 's/MAIL_CMDS_zealix_//g' >> /tmp/mailcmds
---------kmail_filter_mailcmds.sh END------------------------------------


定时上线: 每5分钟上线一次处理一下邮件命令,如果没有STICK,则第6分钟下线
#crontab -e
# m h  dom mon dow   command
0,5,10,15,20,25,30,35,40,45,50,55    *    *  *   *   /usr/sbin/remote_access.s
h start
1,6,11,16,21,26,31,36,41,46,51,56    *    *  *   *   /usr/sbin/remote_access.s
h stop


-------------------- remote_access.sh ----------------------------------------

#! /bin/sh

PPP=`/sbin/ifconfig ppp0 2>&1 | grep inet`

case "$1" in
  start)
    [ -n "$PPP" ] || /etc/init.d/networking restart
    /usr/bin/kmail_fetch.sh
    sleep 20
    /usr/bin/exec_mail_cmds.sh
    ;;
  stop)
    [ -e /var/lock/net_stick ] || /etc/init.d/networking stop
    ;;
  *)
    exit 0
esac

exit 0
-------------------- remote_access.sh  END   ---------------------------------


---------------------kmail_fetch.sh      -------------------------------------

#!/bin/bash
dcop --all-sessions --user xianai kmail KMailIface checkMail >/dev/null 2>&1 &


---------------------kmail_fetch.sh END  -------------------------------------


kmail的收邮件是用dcop协议控制的,dcop的详细用法google dcop,很简单!!
在收邮件的时候,kmail会自动用上面的filter规则来过滤邮件

---------------------/usr/bin/exec_mail_cmds.sh  -----------------------------


#!/bin/bash
[ -e /tmp/mailcmds ] || exit 0
cat /tmp/mailcmds | while read line; do
    case $line in
        NET_STICK)  
            touch /var/lock/net_stick
            ;;
        NET_NOSTICK)  
            rm -f /var/lock/net_stick
            ;;
        *)
            true
            ;;
    esac
done

cat /dev/null > /tmp/mailcmds
---------------------/usr/bin/exec_mail_cmds.sh END --------------------------

你愿意可以自己扩展命令种类和处理方式




iii) dell 主机的配置
主要任务:
    *定时收取邮件,更新/etc/hosts
    *每分钟探测是否 dell->zealix->dell的vpn的回路是畅通的,
     如果不畅通,则建立vpn
 
 
/etc/hosts内容
127.0.0.1       localhost
xxx.xxx.xxx.xxx   zealix
192.168.0.2     ibm
192.168.0.3     dell
10.0.0.2        zealix-tun
10.0.0.1        dell-tun
192.168.1.68    dell-soft

 
ssh&sshd配置
参看zealix主机配置


kmail的配置
类似zealix中,邮件过滤脚本为update_ppp_add.sh
------------------------  update_ppp_add.sh  ---------------------------------


#!/bin/bash
grep "^[0-9]" > /home/xianai/home_address.txt
ADDRESS=`cat /home/xianai/home_address.txt`
sed -e "s/.*zealix$/$ADDRESS   zealix/g" /etc/hosts > /home/xianai/hosts

------------------------- update_ppp_add.sh  END -----------------------------



crontab配置:
root@dell# crontab -e
# m h  dom mon dow   command
1,6,11,16,21,26,31,36,41,46,51,56  *    * * *    /home/xianai/auto_kmail_fetch

.sh ; cp -f /home/xianai/hosts /etc/hosts

0-59  *    * * *    /home/xianai/auto_link_home.sh


----------------------/home/xianai/auto_kmail_fetch.sh -----------------------

#!/bin/bash
dcop --all-sessions --user xianai kmail KMailIface checkMail >/dev/null 2>&1 &


sleep 15
---------------------/home/xianai/auto_kmail_fetch.sh END---------------------



VPN的建立
原理(from man ssh):
    ssh 支持两种方式的vpn建立方式,基于ip和以太网协议的,我采用的前者,
    因为显然,overhead代价比后者低基于ip的vpn的建立的时候,
    ssh会在双方机器上产生两个tun设备,它们之间通过点对点连接之后,
    其它双方的子网通过两边的tun设备以及按照静态路由互相连接,
    达到互相访问的效果

实现:
auto_link_home.sh
-----------------------auto_link_home.sh ----------------------------------
#!/bin/bash


TUN=`/sbin/ifconfig tun2 2>&1 | grep Link`
TUN_CONFIGED=`/sbin/ifconfig tun2 2>&1 | grep P-t-P`

#由于网络连接不稳定的种种原因,可能出现tun2已经出现,但是没有被正确配置的情况


#探测回路之前重新配置一下
if [ -n "$TUN" ] && [ -n "$TUN_CONFIGED" ]; then
    /sbin/ifconfig tun2 10.0.0.1 pointopoint 10.0.0.2
    route add -net 192.168.2.0/24 gw 10.0.0.2 tun2
fi

#三行命令探测 dell-->zealix-->dell的回路是否真的畅通,你还有什么方式呢 :)?
touch /tmp/not_linked
ssh zealix-tun "ssh dell-tun 'rm /tmp/not_linked' " >/dev/null 2>&1 &
sleep 10


[ -e /tmp/not_linked ] || exit 0
STALE_PID=`pgrep -f 'ssh -f -w 2:2 zealix'`
[ -n "$STALE_PID" ] && kill -9 $STALE_PID >/dev/null 2>&1
ssh -f -w 2:2 zealix "/home/xianai/dell_tun.sh " > /dev/null 2>&1 &
sleep 10
touch /home/xianai/cronlink.txt


TUN=`/sbin/ifconfig tun2 2>&1 | grep Link`
[ -n "$TUN" ] || exit 0

#创建两个tun设备的点对点连接
/sbin/ifconfig tun2 10.0.0.1 pointopoint 10.0.0.2

#让192.168.0.0以内的机器能访问到家里的2.0网段的机器
route add -net 192.168.2.0/24 gw 10.0.0.2 tun2
-----------------------auto_link_home.sh END ---------------------------------

-

--------------------dell_tun.sh@zealix----------------------------------------


#!/bin/bash

TUN=`/sbin/ifconfig tun2 2>&1 | grep Link`
[ -n "$TUN" ] || exit 0

#建立tun 点对点连接
ifconfig tun2 10.0.0.2 pointopoint 10.0.0.1

#让192.168.2.0以及zealix能顺畅访问0.0 以及1.0网络的机器
route add -net 192.168.0.0/24 gw 10.0.0.1 tun2
route add -net 192.168.1.0/24 gw 10.0.0.1 tun2

---------------------dell_tun.sh@zealix END ----------------------------------



iv) 可能的变通
我的网络配置有个特殊的情况,就是192.168.0.0的机器的网关是dell,
因此只要在dell这边配置route就可以了,但是可能存在的情况,是dell只是
192.168.0.0网中的其中一台,不是网关,如果这个时候,你想把zealix和
192.168.0.0任何一台互访的话,那么两边的tun设备就需要设成192.168.0.0网内的地址,

如在zealix上:
ifconfig tun2 192.168.0.7 pointopoint 192.168.0.6
在dell上:
ifconfig tun2 192.168.0.6 pointopoint 192.168.0.7
/usr/sbin/arp -sD 192.168.0.7 eth2 pub
arp的命令的目的是让其它机器知道192.168.0.7的包的投送对象是dell的eth2那个网卡,

到了dell这边,里面是有正确的route的。

总而言之,了解整个过程以后,每个人可以根据自己的环境作更换。


最后多说两句,写的好累阿~,
xdjm们要给点掌声啊~~
没有功劳也有苦劳阿~~ !!



发信人: LinuxLover (lilo), 信区: LinuxUnix
标  题: Re: [转载] 自动vpn配置详细方案与配置
发信站: 南京大学小百合站 (Thu Dec 20 11:27:04 2007)

你这个东东强则强矣,但是搞得太复杂了,前面很大一部分内容其实与创建vpn无关,而后
面有关vpn的部分又太少了点,太多脚本容易让人晕菜:)
我来点简单的,呵呵。

正好这两天也要搞这个东东,网络盲瞎摸索了,写点东西留作备忘,也拿出来给大家批评
指正。

vpn首先是创建一个点对点的连接,至于组成network那就要再写路由表了,我们只关注前
面一部分,创建点对点连接,路由表的部分个人需求和情况不同就不说了。当然建立vpn有
各种办法,这只是一种基于ssh的方法而已。

参考ssh manpage中SSH-BASED VIRTUAL PRIVATE NETWORKS这一段,实现一个简单的点对点
连接,ssh命令用到的参数是-f -w,这个大家自己看看手册就是了。

一些约定:本地机器用local表示,远程机器用remote表示,local和remote必须能够互相
用ssh登录。
local和remote之间可能通过n台机器、跨过n个网段连接起来,我们的目标就是建立一个隧
道,使得这中间的一切对我们透明。在此隧道的基础之上,想怎么玩那是就怎么玩。

1. 配置文件
文中提到的ssh和sshd的配置,我给个简化版,并稍作解释。
在local和remote机器中都必须开启ssh服务,并且配置文件作如下改动:
文件/etc/ssh/sshd_config中
添加以下一行
PermitTunnel yes
文件/etc/ssh/ssh_config中
添加以下两行
Tunnel yes
TunnelDevice x:y
这里要解释一下TunnelDevice x:y,原文中直接给了TunnelDevice 2:2,没有解释一下,
实际上x和y是建立p2p连接的两个tunnel设备的设备号,根据你自己创建的tun设备自己改
写。
这个tunnel设备,是虚拟出来的,local和remote各自虚拟一个tun设备(/dev/net/tun,注
意:两台机器都必须支持tun设备,请查看自己的内核配置文件,如果是以模块方式编译的
,须modprobe tun)

2. tun设备
关于这一点,也有值得商榷的地方,原文提到ssh创建tun设备,但是ssh可以创建tun设备
吗?manpage中没有看到,反正我是用tunctl管理tunnel设备,debian下面装个uml-utili
ties即可。在local和remote上都要创建tun设备,用如下命令
$tunctl -f /dev/net/tun -u root -t tun0
这样就创建了一个0号tun设备,tun设备就是隧道两端的入口。这里的0可以用其他数字代
替,但是自己要记得在哪台机器上创建的tun的设备号是多少,因为这与前面ssh_config中
的配置有关。比如local上创建了tunx,remote上创建了tuny,那么local中配置文件就应
该是TunnelDevice x:y,而remote中配置文件就应该是TunnelDevice y:x,这一点搞混了
的话就不行了。

创建完毕之后需要配置tunnel设备,这跟用ifconfig配置eth0一样的。
我们假设local上tun设备为tun0,地址设为10.1.1.1,renmote上为tun1,地址设为10.1.
1.2,那么使用如下命令即可:
在local上
$ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
$route add -net 10.1.1.0/24 gw 10.1.1.2 tun0
在remote上
$ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
$route add -net 10.1.1.0/24 gw 10.1.1.1 tun1
这样local的tun0设备地址为10.1.1.1,remote的tun1地址为10.1.1.2,并且互为网关。(
需要说一下的是,ssh manpage上这一段似乎有些错误,不知道是不是手册太老了)

3. 建立连接
如果以上步骤都完成了,建立连接就很简单了。
在local上ssh -f -w 0:1 remote's ip true
这里remote的ip显然不是前面说的tun设备地址,而是remote的eth0的ip地址了。

4. 测试
此时在local上ping 10.1.1.2和在remote上ping 10.1.1.1都可以成功了,两台机器之间的
连接由tun设备搞定,接下来就可以改local和remote的路由表了,使得两个主机所在的网
络之间的连接透明化。


Tags: fedora, 百合
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments