以Linux提供Client-to-LAN與LAN-to-LAN的VPN環境

以Linux提供Client-to-LAN與LAN-to-LAN的VPN環境

一,            前言

對於大型的企業而言,要聯繫分屬不同區域的分公司所耗費的通訊成本,往往是一項極為沉重的負擔。尤其是每個分公司都會擁有各自獨立的區域網路架構,如果說各分公司之間想要共享特定的網路資源或是彼此的資訊,將會是一個相當複雜的問題,尤其是當A分公司的使用者想要取用BC分公司的資源時,這樣的問題將會更形複雜。因此,面對這樣的情況,我們勢必需要提出一個有效方案來解決這樣的困難點。

所幸,透過企業虛擬網路VPNVirtual Prinate Network﹞的概念,我們可以把分屬於各地的企業分部虛擬成為一個共同的網路。如下圖﹝一﹞所示,過去企業想要把各地的分公司整合為同一個虛擬網路時,需要在各地的分公司之間透過專線的方式來連結網路,對於企業而言這樣的網路架構,需要耗費高昂的線路維護成本與租金,而且當企業內的使用者出差到其他地方時,如果想要連接回公司的虛擬網路,還必須要透過長途電話撥接的方式,透過公司所架設的PPP SERVER來登入公司內部網路,整體而言所耗費的成本將相當可觀。
(),以專線和電話所建立的企業虛擬網路

        因此,透過網際網路來連結各企業分部,取代過去的專線連結與長途撥接,將會是對於企業相當有吸引力的解決方案。如下圖()所示,再各企業分部網路對外連結的部分建立一個具備VPN能力的伺服器,透過各企業分部原本與網際網路的連線,來把各企業的VPN伺服器連結起來,而各企業內的的電腦就可以透過這些建立好的VPN連線,來虛擬成一個共同的企業虛擬網路,使得原本在網際網路兩端的使用者,可以透過同一個網域來彼此溝通,在使用上就有如彼此是在同一個區域網路一樣。同樣的,如果有企業所屬的使用者到了其它的地方,而想要連接回公司的網路時,就可以透過PPTP(Point-to-Point Tunneling Protocol,RFC2637)的方式,透過網際網路連接回公司的VPN伺服器,來進行對企業虛擬網路登入的動作,登入之後,就有如置身於該區域網路的環境,可以隨意的使用企業內部網路所提供的資源。

圖﹝二﹞,透過Internet所架構的VPN網路

        對於Linux的使用者而言,目前Linux已經提供了相當不錯的VPN解決方案,透過這篇文章筆者將舉出實際建構的例子與說明,當然,除了本文所提的VPN方案以外,Linux上面還有其它不同的解法,但限於文章的篇幅,其餘不同的解決方案,我們可以在日後再行討論。


二,            環境規劃

如下圖()所示,為筆者以Linux規劃的測試環境,在兩個網域(LAN-to-LAN)的連結部分,以Linux作為VPN Server,使用的核心版本為Kernel 2.4.17,在上面架設PPTP(Point-to-Point Tunneling Protocol)PPP(Point to Point Protocol)SSH(Secure Shell)伺服器。而實驗時在兩個網域外連接回虛擬網路的Client端則為Windows 2000的主機,之所以使用Windows 2000的原因為目前大多數PC或是筆記型電腦的使用者主要是以MS Windows平台為主,而Windows 2000環境是目前許多人採用的平台之一。



(),以Linux建構的VPN網路環境規劃


三,            建構環境

Linux建立VPN Server時,我們還需要在核心加入NAT (Network Address Translation)PPP的機制,以筆者所選擇的2.4.17核心版本為例,在編譯核心時,我們需要加入以下的功能

*
* Networking options
*

Network packet filtering (replaces ipchains) (CONFIG_NETFILTER) [Y/n/?]
  Network packet filtering debugging (CONFIG_NETFILTER_DEBUG) [Y/n/?]

*
*   IP: Netfilter Configuration
*
Connection tracking (required for masq/NAT) (CONFIG_IP_NF_CONNTRACK) [N/y/m/?] (
NEW) m
  FTP protocol support (CONFIG_IP_NF_FTP) [N/m/?] (NEW) m
  IRC protocol support (CONFIG_IP_NF_IRC) [N/m/?] (NEW) m
IP tables support (required for filtering/masq/NAT) (CONFIG_IP_NF_IPTABLES) [N/y
/m/?] (NEW) m
  limit match support (CONFIG_IP_NF_MATCH_LIMIT) [N/m/?] (NEW) m
  MAC address match support (CONFIG_IP_NF_MATCH_MAC) [N/m/?] (NEW) m
  netfilter MARK match support (CONFIG_IP_NF_MATCH_MARK) [N/m/?] (NEW) m
  Multiple port match support (CONFIG_IP_NF_MATCH_MULTIPORT) [N/m/?] (NEW) m
  TOS match support (CONFIG_IP_NF_MATCH_TOS) [N/m/?] (NEW) m
  LENGTH match support (CONFIG_IP_NF_MATCH_LENGTH) [N/m/?] (NEW) m
  TTL match support (CONFIG_IP_NF_MATCH_TTL) [N/m/?] (NEW) m
  tcpmss match support (CONFIG_IP_NF_MATCH_TCPMSS) [N/m/?] (NEW) m
  Connection state match support (CONFIG_IP_NF_MATCH_STATE) [N/m/?] (NEW) m
  Packet filtering (CONFIG_IP_NF_FILTER) [N/m/?] (NEW) m
    REJECT target support (CONFIG_IP_NF_TARGET_REJECT) [N/m/?] (NEW) m
  Full NAT (CONFIG_IP_NF_NAT) [N/m/?] (NEW) m
    MASQUERADE target support (CONFIG_IP_NF_TARGET_MASQUERADE) [N/m/?] (NEW) m
    REDIRECT target support (CONFIG_IP_NF_TARGET_REDIRECT) [N/m/?] (NEW) m
  Packet mangling (CONFIG_IP_NF_MANGLE) [N/m/?] (NEW) m
    TOS target support (CONFIG_IP_NF_TARGET_TOS) [N/m/?] (NEW) m
    MARK target support (CONFIG_IP_NF_TARGET_MARK) [N/m/?] (NEW) m
  LOG target support (CONFIG_IP_NF_TARGET_LOG) [N/m/?] (NEW) m
  TCPMSS target support (CONFIG_IP_NF_TARGET_TCPMSS) [N/m/?] (NEW) m
ipchains (2.2-style) support (CONFIG_IP_NF_COMPAT_IPCHAINS) [N/y/m/?] (NEW) m
ipfwadm (2.0-style) support (CONFIG_IP_NF_COMPAT_IPFWADM) [N/y/m/?] (NEW) m

*
* Network device support
*

PPP (point-to-point protocol) support (CONFIG_PPP) [N/y/m/?] m
  PPP support for async serial ports (CONFIG_PPP_ASYNC) [N/m/?] (NEW) m
  PPP support for sync tty ports (CONFIG_PPP_SYNC_TTY) [N/m/?] (NEW) m
  PPP Deflate compression (CONFIG_PPP_DEFLATE) [N/m/?] (NEW) m
  PPP BSD-Compress compression (CONFIG_PPP_BSDCOMP) [N/m/?] (NEW) m

*
* Kernel hacking
*
Kernel debugging (CONFIG_DEBUG_KERNEL) [N/y/?] y
  ……
  Magic SysRq key (CONFIG_MAGIC_SYSRQ) [N/y/?] (NEW) y


        筆者預設是把所有會使用到的功能都編入核心或是編譯成模組,各位可以根據自己的情況來加以取捨即可。

        在編譯完了核心之後,筆者在此介紹所需要安裝的套件,所有選擇的套件版本都是在筆者撰寫本文時所下載的,各位可以根據自己的需要,下載更新的版本。


(1)   PPTP 伺服器è主要是用來提供給在網際網路上的使用者透過PPTP協定撥入我們的PPTP伺服器,連接上伺服器內部的VPN網路。整體的運作概念如下圖(四)所示,我們可以透過PPTP Client登入遠方VPN網域對外的PPTP伺服器。


(四),PPTP伺服器與PPTP用戶端(Windows 2000)

有關PPTP Server的程式碼,讀者可至網址 http://poptop.lineo.com 下載最新的版本,安裝完PPTP後,要把samples目錄下的pptpd.conf拷貝到/etc目錄下,並且修改其中指定的IP位址設定,例如筆者設定如下

localip 192.168.1.2-127                     è屬於伺服器端網域的IP位址
remoteip 192.168.1.128-230             è分配給透過PPTP撥入使用者的IP位址


(2)   PPP 伺服器èPPP通訊協定是在網路連線時,相當常見的通訊協定,不論是用在透過數據機(modem)撥接或是如本文章中所介紹的VPN解決方案,都可以見到PPP通訊協定的存在。如下圖(五)所示,當使用者端透過PPTP與伺服器連線時,使用者程式透過TCP/IP通訊協定傳輸的資料,就會透過PPP協定來傳輸。


(五),PPP+PPTP伺服器與PPP+PPTP用戶端(Windows 2000)


各位讀者在安裝PPP伺服器時,請勿使用Redhat 7.2光碟中附的ppp-2.4.1-2.i386.rpm,該版本的PPP Server會讓Windows的使用者撥入之後產生
” IPCP: timeout sending Config-Requests”的錯誤。如下所示

xxx 15 11:23:07 HLCHOU kernel: PPP BSD Compression module registered
xxx 15 11:23:07 HLCHOU kernel: PPP Deflate Compression module registered
xxx 15 11:23:37 HLCHOU pppd[4020]: IPCP: timeout sending Config-Requests
xxx 15 11:23:37 HLCHOU pptpd[4019]: CTRL: Ignored a SET LINK INFO packet with real ACCMs!
xxx 15 11:23:37 HLCHOU pppd[4020]: Connection terminated.

讀者請自行到 http://www.samba.org/ppp 下載最新的PPP Server程式(筆者使用的版本為ppp-2.4.1)。安裝完PPP後,請執行 mknod /dev/ppp c 108 0,以便於在/dev 目錄下產生對應的的裝置檔案。

(3)PPTP 連線核心更新檔è由於我們在Linux上安裝的VPN伺服器,會把NAT的功能包含在裡面,因此對於NAT本身的服務機制來說,如果使用者端沒有安裝PPTP連線的核心更新檔的話,那在該NAT伺服器網域內的使用者將會無法透過該NAT伺服器連結到網域外的PPTP Server。如下圖()所示,當Linux的伺服器加上了PPTP的核心更新檔後,就可以允許在NAT內部網域的使用者透過NAT伺服器使用PPTP通訊協定連結到外部網路的PPTP伺服器。

(),在Linux NAT Server內部網域,由Client透過PPTP連線連接外部網路

讀者可至 http://www.impsec.org/linux/masquerade/ip_masq_vpn.html  下載所需的Kernel Patch。安裝的動作如下所示(筆者的核心為2.4.17)

[root@hlchou VPN]# patch -p0 < ./netfilter-pptp-2.4.17-rev2.patch
patching file linux/Documentation/Configure.help
patching file linux/include/linux/netfilter_ipv4/ip_conntrack.h
patching file linux/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
patching file linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
patching file linux/include/linux/netfilter_ipv4/ip_nat_pptp.h
patching file linux/net/ipv4/netfilter/Config.in
patching file linux/net/ipv4/netfilter/Makefile
patching file linux/net/ipv4/netfilter/ip_conntrack_pptp.c
patching file linux/net/ipv4/netfilter/ip_nat_pptp.c
[root@hlchou VPN]#

編譯核心時,請記得把支援PPTP的選項打開,並在起始NAT封包過濾的機制時,載入ip_conntrack_pptp.o 與 ip_nat_pptp.o 兩個核心模組,就可以讓我們設定的Linux NAT Server支援網內的PPTP對外的連線。

(4)   SSH伺服器è如下圖()所示,SSH可以讓使用者在遠端的SSH伺服器上建立一個終端機的介面,透過登入來操作遠端的電腦,SSH會透過SSL(Secure Sockets Layer)函式庫提供的加密機制來進行連線,因此透過SSH所建立的連線機制,在TCP層以上都是會被加密處理的。筆者使用的為OpenSSH,可以可以到 http://www.openssh.com/ 下載最新的版本。

() SSH伺服器與SSH使用者端的連線

        由於在透過SSH建立VPN環境時,我們需要讓SSH Server端可以不用輸入使用者的帳號密碼,以便於之後連線上的便利,所以我們要在SSH Client端先產生SSHPublic Key,再拷貝到SSH Server端的帳號下,就可以在每次SSH Client登入時,省去檢測密碼的流程,而直接登入了。首先,筆者在SSH Server端建立一個hlchou的帳號,並在SSH Client端以root執行 “ssh-keygen -t rsa” ,如下所示,執行後不要輸入任何值,直接按Enter到結束即可。

[root@localhost openssh-3.1p1]# ./ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
6b:c1:9c:b5:86:20:0f:dd:b3:68:41:fc:90:26:bd:e7 root@localhost.localdomain
[root@localhost openssh-3.1p1]#

        會在root帳號下的.ssh目錄產生檔案id_rsa.pub,之後把檔案拷貝到SSH Serverhlchou帳號的.ssh目錄,把檔名改為authorized_keys。並且把hlchou帳號下的.ssh目錄權限設為755,而檔案authorized_keys權限設為644

        最後,要測試這個動作是否正確,請在SSH Server上把sshd執行起來,並在SSH Client端執行
        “ssh –P 140.96.85.202 –l hlchou”    來測試是否可以登入。

(5)     sudo(superuser do)è提供給一般的使用者透過sudo程式執行屬於特權等級使用者(Root)才能執行的程式。各位可以到 http://www.courtesan.com/sudo/ 網址去下載安裝即可。請在VPN Server端的部分執行visudo修改檔案”/etc/sudoers”,加入以下資料
“hlchou ALL=NOPASSWD: /usr/sbin/pppd ,/sbin/route”

(6)設定NAT環境與建立LAN-to-LAN的連線

        要在Linux 2.4.17版本的核心中設定NAT的環境,各位還需要安裝iptables的套件(可到http://netfilter.samba.org/下載),在安裝完之後,我們就已經具備了可以開始規劃VPN網路環境的條件了。首先,網路環境設定如下圖﹝八﹞所示,左方為PPP Server,右方為PPP Client,啟動VPN連線時,就由右方的PPP Client主動與PPP Serevr進行VPN環境的連線。

圖﹝八﹞,LAN-to-LAN VPN網路規劃

        先確定VPN Serversshdpptpd是否有被執行,之後執行以下的指令

/usr/sbin/pppd updetach noauth passive pty “/usr/bin/ssh -P 140.96.85.202 -lhlchou -o Batchmode=yes sudo /usr/sbin/pppd nodetach notty noauth” ipparam vpn 192.168.0.2:192.168.0.1
insmod /lib/modules/2.4.17/kernel/net/ipv4/netfilter/ip_tables.o
insmod /lib/modules/2.4.17/kernel/net/ipv4/netfilter/ip_conntrack.o
insmod /lib/modules/2.4.17/kernel/net/ipv4/netfilter/iptable_nat.o
insmod /lib/modules/2.4.17/kernel/net/ipv4/netfilter/ipt_MASQUERADE.o
insmod /lib/modules/2.4.17/kernel/net/ipv4/netfilter/ip_conntrack_pptp.o
insmod /lib/modules/2.4.17/kernel/net/ipv4/netfilter/ip_nat_pptp.o
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/ppp0/forwarding
route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.0.1
/usr/bin/ssh -P 140.96.85.202 -lhlchou -o Batchmode=yes sudo route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.0.2

就可以順利的建立起LAN-to-LANClient-to-LANVPN環境了。

我大略說明一下這些指令的意義,首先就是透過pppdssh建立兩個LAN之間的VPN連線,由於這段程式碼是在VPN Client端執行的,所以在第一行的ssh連線建立所指的IP位址就是VPN Server140.96.85.202。之後就是載入VPN環境的核心模組與透過iptables設定VPN,到了最後兩行則分別設定了VPN ClientVPN Server兩端的路由,讓屬於192.168.x.x 的虛擬網路位址在VPN連線中可以彼此互通。

        當然,如同我們在文章前所提到的,除了提供LAN-to-LAN的解決方案以外,我們還必須要提供一個Client-to-LANVPN環境,既然我們已經在Linux伺服器上執行了PPTP伺服程式,接下來我們要做的事情就是在使用者端的Windows2000環境中,也建立起PPTP的連線設定,以便於讓在不同區域的使用者也可以透過Windows2000登入我們所建立的虛擬網路環境。
       
如下圖()所示,首先我們新增一個撥號連線

(),在Windows 2000,產生新的撥號連線


        接下來在網路連線類型時,選擇透過Internet撥號到私人的網路

(),設定為透過Internet撥號到私人的網路中

        由於筆者所在的環境已經具備有對外的連線設備,所以我並不需要先透過電話撥接到ISP後才能上網,因此如下圖(十一)所示,我選擇了不透過撥接起始連線的設定,各位可以根據自己所屬環境的不同來決定。
(十一),在這可以選擇要透過modem電話撥接或是透過已存在的網路連線,本例中筆者是透過自己內部的LAN連線


        如下圖(十二),筆者在此輸入實驗環境中PPTP伺服器的網路位址


(十二),輸入所要連線的PPTP伺服器位址

        輸入連線名稱,隨即完成全部的設定動作。
(十三),輸入連線的名稱,隨即完成全部的PPTP連線設定動作

        最後,由於筆者沒有解決Linux PPTP ServerWindows 2000之間加密的問題,所以如下圖(十四)所示,請各位在PPTP連線的 要求資料加密(如果沒有加密就中斷連線)” 選項中,選擇不要使用這項功能。


(十四),請取消 要求資料加密(如果沒有加密就中斷連線)”

        之後讀者只要在Linux伺服器上面為該名使用者開啟一個帳號與密碼,在該使用者透過PPTP連線時,輸入指定的帳號密碼即可。


四,            運作分析

        如下圖(十四)所示,在圖的上方式介紹了PPTP連線初始化的過程,首先會由PPTP Client對PPTP Server送出 “Start-Control-Connection Request” ,等待Server回應後再送出 “Outgoing-Call Request”,之後送出 “Set-Link-Info”,便算是完成了PPTP連線的建立。再來就會開始進行PPP協定的初始化,之後在PPTP+PPP上面的通訊協定,就可以順利的透過這些建立好的機制來傳送資料了。而用來傳送PPP協定的GRE(Generic Routing Encapsulation),主要的目的就是用來封裝(Tunneling)不同的通訊協定,詳細的資料各位可以參考RFC1702(Generic Routing Encapsulation http://www.faqs.org/rfcs/rfc1701.html)RFC1702(Generic Routing Encapsulation over IPv4 networkshttp://www.faqs.org/rfcs/rfc1702.html)


(十五)PPTP連線初始化與資料傳遞


如下圖(十五)所示,兩端的LAN透過PPP+SSH的方式可以建立起一個加密的通道連線,讓兩端的網路資料可以透過PPP協定來傳輸,而且又具備了SSH本身加密的好處。透過這樣的架構兩端網路的使用者就如同置身於同一個虛擬網路一般,可以輕易的接觸到另一端的網路資源。


(十六),以PPP+SSH所建立的LAN-to-LAN架構

PPP+SSH建立VPN網路最大的問題就是對於網路封包的傳輸的浪費,因為要傳送一個簡單的封包就要透過許多層的封包檔頭來傳遞,往往會造成珍貴網路頻寬的浪費。如果以後還有機會的話,我會為各位介紹其它的VPN解決方案,讓更多人可以了解這部分的技術。


五,結語

        隨著寬頻網路的逐漸普及化,我們會發現資訊安全的重要性在我們週遭以慢慢的浮現,由於人們花費在網際網路上的時間增加,相對的不論是生活或是工作都極有可能讓自己暴露在不安全的資訊架構當中。

        本文所介紹的方式,主要是透過PPTP ServerPPP+SSH的解決方案,其實在Linux的環境中還有一個可以參考的就是透過FreeS/WAN計劃所提供的IPSec機制,來建立一個Client-to-Lan或是Lan-to-LanVPN環境,限於文章的篇幅我們不容易一次把所有的方案討論完畢,讀者們如果對於這樣的議題有興趣,也可以自行根據本身網路安全環境的需求,尋求不同解決方案的資訊。

        當然囉,本文的撰寫最希望的就是可以讓更多人了解到Linux在網路功能的強大,進而善加利用它所提供的優異網路機制,各位如果有任何問題歡迎與我聯繫,我的E-Mailhlchou@mail2000.com.tw


六,參考資料

1﹞Linux VPN Masquerade, http://www.impsec.org/linux/masquerade/ip_masq_vpn.html
4﹞Virtual Private Networks Frequently Asked Questions,http://kubarb.phsx.ukans.edu/~tbird/vpn/FAQ.html
5﹞Point-Point Tunneling Protocol (PPTP) FAQhttp://www.microsoft.com/ntserver/ProductInfo/faqs/PPTPfaq.asp
6﹞在Windows 95/98/ME/2000 Professional 安裝PPTP的資訊,http://www.moe.edu.my/pptpbeta
(7) VPN PPP-SSH Mini-HOWTO,http://www.linuxdoc.org/HOWTO/mini/ppp-ssh/