Linux搭建VPN

本文介紹在安裝CentOS操作系統的Xen VPS上,如何搭建PPTP VPN服務。包括PPTP的安裝、配置,以及相應的iptables規則。本文暫時不涉及PPTP流量控制的部分,等抽空學明白了FreeRADIUS,再來寫續篇。2011年7月20日更新:在安全建議這一部分,增加了使用不同的IP地址,分別提供VPN服務和Web等其他常規服務,以及使用不同IP地址時如何書寫iptables規則的內容。

寫在前面

在Godaddy一美元COM域名的慫恿下,這幾天先是拿到了這個gnailuy.com,然後覬覦了很久的VPS也就順便到手了。所以說萬事嘛,總是要有個開端。

按照之前的構想,下個月起這個VPS將由我和幾個好朋友合租,配置虛擬主機,各自建立自己的小網站,還能合用VPS上的VPN服務。從成本上考慮,只要有些鑽研技術的精神,加上幾個志同道合的朋友,合租一臺不太高端的VPS自建服務器,應該還是低於同時購買域名、Web託管以及VPN這幾樣的成本之和的。這是第一個月,我們會先熟悉熟悉技術,做做各種測試,多學習多發些技術文章,供有同樣想法的朋友們借鑑。

正文

在Google苦海里遊了兩天兩夜,終於完成了PPTP VPN還有這個Wordpress小站的基本配置,今天先寫一下VPN。這些天因爲嫌Google中文首頁太醜,搜索資料的時候大都是用英文,本來也打算用英文寫這篇文章,但考慮到下面兩個原因,於是作罷:一是到自己這英語寫作能力,實在不濟;二是可能熱衷於搭建VPN的個人或者團體,大概也許基本都是在中國大陸上網的吧,o(∩∩)o…

之所以選擇PPTP VPN,是考慮到客戶端連接起來會比較方便。我們幾個人主要都是在Linux Desktop、Windows還有Android上使用VPN,這些終端原生都有連接PPTP的客戶端。當然還有一個原因,就是我們購買的VPS是基於Xen PV技術的,可以搭建PPTP。這個原因本來其實是結果,當初要買基於Xen PV的而不是OpenVZ的,就是因爲打算在上面搭建PPTP服務。BTW,Xen PV是種半虛擬化技術,不能跑Windows,但據說比全虛擬化的Xen HVM跑Linux效率高。

平臺簡介

  • “硬”件平臺:Xen PV, 215M Memory, 512M Swap, 1T Transfer
  • 操作系統:CentOS release 5.6 (Final)
  • 內核:2.6.18-194.32.1.el5xen i686 i386 GNU/Linux
  • 網絡:1 IP, 1 Network Adapter(eth0)

配置概覽

PPTP的配置主要有下面五個步驟:

  • 驗證內核是否加載了MPPE模塊
  • 安裝所需的軟件包
  • 配置PPP和PPTP的配置文件
  • 打開內核的IP轉發功能
  • 啓動pptpd守護進程
  • 配置iptables防火牆放行和轉發規則

詳細步驟

開機以後,首先是登錄VPS。我平時用Linux,就直接ssh命令登錄上去。如果是在Winodws下,推薦使用PuTTY,有一點需要注意,就是連接之前最好把字符集設置成UTF-8,因爲Linux默認的locale都是UTF-8了,如果出現非ASCII字符,不設置字符集就會出現亂碼,具體的設置方法Google知道。

下面的所有配置操作都需要root權限,如無特別說明,所有命令都在root的家目錄下執行。順便,最好在VPS上禁用root直接登錄,儘量建立一個普通用戶然後su到root,具體細節偏題了,也請自行Google。

1、驗證內核是否加載了MPPE模塊:

內核的MPPE模塊用於支持Microsoft Point-to-Point Encryption。Windows自帶的VPN客戶端就是使用這種加密方式,主流的Linux Desktop也都有MPPE支持。其實到了我們這個內核版本,默認就已經加載了MPPE,只需要使用下面命令驗證一下,顯示MPPE ok即可:

modprobe ppp-compress-18 && echo MPPE is ok

2、安裝所需的軟件包:

–ppp–

PPTP使用PPP協議對用戶數據進行封裝,然後將PPP數據幀封裝在IP數據報裏,經由IP網絡傳播。因此首先需要支持PPP協議,我們使用的完整版CentOS已經自帶了ppp這個軟件包,如果你安裝的是Minial CentOS之類的精簡系統,則可能需要下面命令安裝ppp:

yum install ppp

作爲一個懶人,如果沒有特殊的自定義要求,我一般儘量用yum安裝軟件。只要軟件源裏有,yum比較方便一些,還能自動解決依賴關係。

–pptpd-

有了PPP協議支持,接下來安裝pptpd。首先到這裏找到最新版適合你的平臺的pptpd。CentOS與RHEL通用,Fedora系統則可以使用後綴含fc字樣的包,然後還需要根據內核選擇32位或者64位的包。找到正確的軟件包以後,複製其URL,然後用wget下載到root的家目錄(或者rpm -ivh URL直接安裝也行)。譬如我的32位內核CentOS 5,使用下面命令下載:

wget http://poptop.sourceforge.net/yum/stable/packages/pptpd-1.3.4-2.rhel5.i386.rpm

這篇文章默認不考慮”wget: command not found”此類初級的錯誤。如果看到類似錯誤,一是檢查命令有沒有拼錯,二是yum install it,三是Google it。其實,這篇文章裏總共也用不到幾條容易Not Found的命令。

下載完成後,安裝:

rpm -ivh pptpd-1.3.4-2.rhel5.i386.rpm
–iptables–

同樣,如果不是Minial的系統,應該不會沒有安裝iptables。這是Linux下最流行的防火牆,默認應該就能找到,如果沒有,則:

yum install iptables

然後像是iptables這樣的軟件,對服務器非常重要。雖然還沒有配置防火牆的規則,裝完就打開吧(只要默認放行ssh的22端口就沒問題),打開以後還需要設置一下,在主要的運行級別自動啓動:

/etc/init.d/iptables start chkconfig --level 35 iptables on

3、配置PPP和PPTP的配置文件:

接下來需要對ppp和pptpd進行配置,編輯它們的幾個配置文件。如果有Linux基礎的話,當然推薦使用vi/vim來編輯配置文件。如果不熟悉也不想熟悉vi,那麼可以用更容易上手的nano替換下面我將要使用的vi命令。本文不涉及文本編輯器的基礎知識,只需要知道如何打開文件、編輯文件、保存文件和退出文本編輯器就可以了。

這些配置文件中,#號開頭的行均爲註釋,對配置不起作用。我們不必關心註釋,所以下面我將使用類似

grep ^[^#] /etc/ppp/options.pptpd

這樣的命令,過濾出配置文件中有效的行顯示在本文正文中。你在編輯的時候,只需要添加或修改這些有效的行,把不需要的行前面加上#號註釋掉即可。

–ppp–

配置ppp需要編輯它的兩個配置文件,一個是option(選項)文件,一個是用戶賬戶文件。首先編輯option文件:

vi /etc/ppp/options.pptpd

我編輯這個文件時,它已經是存在的,並且其中的內容也幾乎不需要編輯,如果這個文件不存在,自行創建它並填入下面的有效配置就行了。下面是這個文件中有效的行:

  1. name pptpd
  2. refuse-pap
  3. refuse-chap
  4. refuse-mschap
  5. require-mschap-v2
  6. require-mppe-128
  7. ms-dns 8.8.8.8
  8. ms-dns 8.8.4.4
  9. proxyarp
  10. lock
  11. nobsdcomp
  12. novj
  13. novjccomp
  14. nologfd

其中name後面的pptpd是服務名稱,可以任意修改成你喜歡的名字,在後面的配置中將對應的pptpd替換爲你在這裏修改的名字即可。

接下來的幾行以refuse或者require開頭的指令,是配置拒絕和接受的加密方式,這裏接受的mschap-v2和mppe-128都是較新的比較安全的加密方式,其中mppe-128需要第一步中驗證的內核模塊支持。

另外兩個比較重要的行就是ms-dns了,它們指定VPN使用的DNS服務器。畢竟VPS位於國外,所以推薦使用上面通用的Google Public DNS,當然也可以修改爲你的VPS所在ISP提供的DNS。

剩下後面幾個選項,就不在這裏敘述了,需要知道其含義的童鞋可以參考這個範例文件中的註釋。

接下來修改另一個,存儲着用戶賬戶的文件:

vi /etc/ppp/chap-secrets

這個文件非常簡單,其中用明文存儲VPN客戶的用戶名、服務名稱、密碼和IP地址範圍,每行一個賬戶:

  1. username1    pptpd    passwd1    *
  2. username2    pptpd    passwd2    *

其中第一第三列分別是用戶名和密碼;第二列應該和上面的文件/etc/ppp/options.pptpd中name後指定的服務名稱一致;最後一列限制客戶端IP地址,星號表示沒有限制。

–pptpd–

下面編輯pptpd的配置文件:

vi /etc/pptpd.conf

這個文件中有效的行也很少:

  1. option /etc/ppp/options.pptpd
  2. logwtmp
  3. localip 192.168.0.1
  4. remoteip 192.168.0.207-217

其中option選項指定使用/etc/ppp/options.pptpd中的配置;logwtmp表示使用WTMP日誌。

後面兩行是比較重要的兩行。VPN可以這樣理解,Linux客戶端使用一個虛擬網絡設備ppp0(Windows客戶端也可以理解成VPN虛擬網卡),連接到服務器的虛擬網絡設備ppp0上,這樣客戶端就加入了服務器端ppp0所在的網絡。localip就是可以分配給服務器端ppp0的IP地址,remoteip則是將要分配給客戶端ppp0(或者虛擬網卡)的。

這兩項都可以是多個IP,一般localip設置一個IP就行了,remoteip則視客戶端數目,分配一段IP。其中remoteip的IP段需要和localip的IP段一致。

localip和remoteip所處的IP段可以隨意些指定,但其範圍內不要包含實際網卡eth0的IP地址。一般情況下,使用上面配置文件中的配置就好使了,你需要做的只是把192.168.0.207-217這個IP區間修改成你喜歡的192.168.0.a-b,其中1<a<b<255。

4、打開內核的IP轉發功能:

要使VPN服務器可以作爲網絡請求的中轉代理,能夠使客戶端通過VPN訪問Internet,還需要開啓內核的IP轉發功能。可以編輯配置文件:

vi /etc/sysctl.conf

找到其中的行:

net.ipv4.ip_forward = 0

修改爲:

net.ipv4.ip_forward = 1

然後執行下面命令使上述修改生效:

sysctl -p

5、啓動pptpd守護進程:

上面配置完成後,就可以啓動pptpd進程並設置自動啓動了,和上面iptables的例子類似:

/etc/init.d/pptpd start chkconfig --level 35 pptpd on

6、配置iptables防火牆放行和轉發規則:

最後,還需要配置防火牆。這裏配置防火牆有三個目的:一是設置默認丟棄規則,保護服務器的安全;二是放行我們允許的數據包,提供服務;三是通過配置nat表的POSTROUTING鏈,增加NAT使得VPN客戶端可以通過服務器訪問互聯網。總之我們的原則就是,只放行我們需要的服務,其他統統拒絕。

首先介紹跟PPTP VPN相關的幾項:

  • 允許GRE(Generic Route Encapsulation)協議,PPTP使用GRE協議封裝PPP數據包,然後封裝成IP報文
  • 放行1723端口的PPTP服務
  • 放行狀態爲RELATED,ESTABLISHED的入站數據包(正常提供服務的機器上防火牆應該都已經配置了這一項)
  • 放行VPN虛擬網絡設備所在的192.168.0.0/24網段與服務器網卡eth0之間的數據包轉發
  • 爲從VPN網段192.168.0.0/24轉往網卡eth0的出站數據包做NAT

如果你其他的防火牆規則已經配置好無需改動,只需要增加上述相關VPN相關的規則,那麼執行下面幾條命令即可(第三條一般不用執行,除非你原來的防火牆連這個規則都沒允許,但是多執行一遍也無妨):

  1. iptables -A INPUT -p gre -j ACCEPT
  2. iptables -A INPUT -p tcp -m tcp --dport 1723 -j ACCEPT
  3. iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  4. iptables -A FORWARD -s 192.168.0.0/24 -o eth0 -j ACCEPT
  5. iptables -A FORWARD -d 192.168.0.0/24 -i eth0 -j ACCEPT
  6. iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

上述的IP段192.168.0.1/24可能需要修改成/etc/pptp.conf中你配置的localip和remoteip所在地IP段。

在我們這臺服務器上,還需要一些其他的服務:

  • 22端口的SSH(非常重要!如果不小心連這個都忘了,基本就只能給VPS服務商發Ticket了)
  • 21端口的FTP控制
  • 80端口的Web服務
  • 允許響應各種icmp請求

根據上述需求,加上服務器的基本要求,我寫了下面的shell腳本。這個腳本默認DROP掉沒有明確允許的規則,然後允許包括上面VPN相關的規則和上述幾項其他服務所需的規則。可以根據你的實際需求,修改這個腳本,然後執行這個腳本快速部署iptables規則。

  1. #!/bin/bash
  2. ### Clear Old Rules
  3. iptables -F
  4. iptables -X
  5. iptables -Z
  6. iptables -t nat -F
  7. iptables -t nat -X
  8. iptables -t nat -Z
  9. ### * filter
  10. # Default DROP
  11. iptables -P INPUT DROP
  12. iptables -P FORWARD DROP
  13. iptables -P OUTPUT DROP
  14. # INPUT Chain
  15. iptables -A INPUT -p gre -j ACCEPT
  16. iptables -A INPUT -i lo -p all -j ACCEPT
  17. iptables -A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
  18. iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
  19. iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
  20. iptables -A INPUT -p tcp -m tcp --dport 1723 -j ACCEPT
  21. iptables -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
  22. iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  23. # OUTPUT Chain
  24. iptables -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
  25. # FORWARD Chain
  26. iptables -A FORWARD -s 192.168.0.0/24 -o eth0 -j ACCEPT
  27. iptables -A FORWARD -d 192.168.0.0/24 -i eth0 -j ACCEPT
  28. ### * nat
  29. # POSTROUTING Chain
  30. iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

需要注意的是,這個腳本開頭首先清除掉了所有iptables規則,然後才部署新的規則,如果你需要保留你機器上現有的規則,請千萬不要執行前面的清除語句,或者做好舊規則的備份再做實驗:

iptables-save > iptables.backup

如果想恢復使用上面命令做好的備份,可以:

iptables-resotre iptables.backup

最後,如果確定所有的iptables規則已經合乎你的心意,就可以執行下面命令,將iptables規則保存下來。

/etc/init.d/iptables save

安全建議

在Twitter上得到了@alexwwang @helijohnny的指點,知道VPN與這個網站放在一起,可能不安全。他們建議我爲VPS增加一個IP,可以讓VPN服務和Web走不同的IP,這樣就不會因爲Web網站發表的內容輕易暴露VPN服務器的IP了。之前我只是在測試機上測試過,今天終於新購得一個IP地址,得以把這一部分補全。

單網卡配置多個IP地址

CentOS下單網卡配置多個IP很容易。例如,假設現在網卡eth0已經有一個IP地址是123.123.123.123/24,想要增加一個IP是123.123.123.124/24,可以在/etc/sysconfig/network-scripts/目錄下增加一個新的虛擬網卡配置文件ifcfg-eth0:0。想省事的話可以直接把ifcfg-eth0複製成ifcfg-eth0:0。然後編輯其內容,例如:

  1. DEVICE=eth0:0
  2. BOOTPROTO=static
  3. ONBOOT=yes
  4. IPADDR=123.123.123.124
  5. NETMASK=255.255.255.0

虛擬網卡eth0:0配置的信息看起來有些少,其實它會共享實際設備eth0的配置信息,因此如上簡單的配置就夠了。另外如果在這張網卡上還需要添加更多的IP地址,照此例增加eth0:1、eth0:2等等虛擬設備既可。

多IP的iptables配置

然後關於iptables配置,思路就是在INPUT鏈上使用-d區別目的IP,只在Web等服務使用的IP上放行22和80等幾個端口,VPN服務的IP上只放行1723端口。

如果喜歡的話也可以爲新增加的IP綁定一個不同的域名,只要防火牆配置好了,然後VPN使用的IP域名都不公開,理論上是挺難找到VPN服務地址的,這也是自建VPN的一個好處。這裏再提供一個iptables規則的配置腳本,與上面的腳本類似,只是做了少量的修改,適用於多IP的情況:

  1. #!/bin/bash
  2.  
  3. # Clear Old Rules
  4. iptables -F
  5. iptables -X
  6. iptables -Z
  7. iptables -t nat -F
  8. iptables -t nat -X
  9. iptables -t nat -Z
  10.  
  11. ### * filter
  12.  
  13. # Default DROP and ACCEPT
  14. iptables -P INPUT DROP
  15. iptables -P FORWARD DROP
  16. iptables -P OUTPUT DROP
  17.  
  18. # INPUT Chain
  19. iptables -A INPUT -p gre -j ACCEPT
  20. iptables -A INPUT -i lo -p all -j ACCEPT
  21. iptables -A INPUT -p tcp -m tcp -d 123.123.123.123 --dport 21 -j ACCEPT
  22. iptables -A INPUT -p tcp -m tcp -d 123.123.123.123 --dport 22 -j ACCEPT
  23. iptables -A INPUT -p tcp -m tcp -d 123.123.123.123 --dport 80 -j ACCEPT
  24. iptables -A INPUT -p tcp -m tcp -d 123.123.123.123 --dport 443 -j ACCEPT
  25. iptables -A INPUT -p tcp -m tcp -d 123.123.123.124 --dport 1723 -j ACCEPT
  26. iptables -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
  27. iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  28.  
  29. # OUTPUT Chain
  30. iptables -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
  31.  
  32. # FORWARD Chain
  33. iptables -A FORWARD -s 192.168.0.0/24 -o eth0 -j ACCEPT
  34. iptables -A FORWARD -d 192.168.0.0/24 -i eth0 -j ACCEPT
  35.  
  36. ### * nat
  37.  
  38. # POSTROUTING Chain
  39. iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

這樣配置完成後,對公開的Web域名進行端口掃描,就只能掃描到80等端口,而VPN服務使用的域名IP不公開,就保證了安全性。我手欠掃描了一下我們的服務器,結果就成了這樣:

  1. [root@sheldon ~]# nmap -sS gnailuy.com
  2.  
  3. Starting Nmap 5.21 ( http://nmap.org ) at 2011-07-20 20:46 CST
  4. Nmap scan report for gnailuy.com (One of our IP address)
  5. Host is up (0.31s latency).
  6. Not shown: 996 filtered ports
  7. PORT STATE SERVICE
  8. 21/tcp open ftp
  9. 22/tcp open ssh
  10. 80/tcp open http
  11. 443/tcp open https
  12.  
  13. Nmap done: 1 IP address (1 host up) scanned in 17.44 seconds
  14. [root@sheldon ~]# nmap -sS vpnservers.domain.name
  15.  
  16. Starting Nmap 5.21 ( http://nmap.org ) at 2011-07-20 20:53 CST
  17. Nmap scan report for vpnservers.domain.name (Our another IP address)
  18. Host is up (0.32s latency).
  19. Not shown: 999 filtered ports
  20. PORT STATE SERVICE
  21. 1723/tcp open pptp
  22.  
  23. Nmap done: 1 IP address (1 host up) scanned in 24.52 seconds

後記

這篇文章是邊爬搜索引擎邊學習邊實驗寫成的,在摸索的過程中學習,確實學到了不少東西。學習和配置服務器的過程中,我不斷的Google到相關的文章,中文的英文的已經有一大把,於是我就在想,我寫這篇文章,應該完成哪些現有的資料尚不完善的地方。技術上我只是個初學者,除了搜索、思考、組織之外,暫時沒有可能創造出新的技術來,於是只好從語言組織、信息翔實程度和對配置細節的解釋上儘量提高本文的含金量,希望成爲中文文章中比較有用的一篇,能夠爲其他有這方面想法的朋友提供一些小小指引。

非常感謝在Twitter上爲我出主意的 @alexwwang 和 @helijohnny,他們的寶貴意見促成了本文目前的樣子。如果本文中還有哪些不足甚至紕漏,請千萬不吝賜教;或者如果你想要和我探討這方面的技術,都歡迎與我聯繫。可以@gnailuy on Twitter,或者也可以在我的About Me頁面找到更多其他聯繫方式。

© 2011, Yuliang Jin. All rights reserved. 
This post is under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章