发信人: 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的路由表了,使得两个主机所在的网 络之间的连接透明化。