1. 程式人生 > >OpenWrt搭建PPTP VPN伺服器過程記錄

OpenWrt搭建PPTP VPN伺服器過程記錄

一個路由器的耗電要比一臺電腦小的多,所以我經常把OpenWrt的路由器當成一臺小的Linux嵌入式系統來用,最近在家裡的路由器上搭建了一個PPTP伺服器服務,這樣我在外面可以輕鬆的連線到家裡的路由器並控制家裡的內網裝置了。當然這個PPTP伺服器的主要作用還是將多個SS節點進行負載均衡和高可用然後轉換為VPN供外網使用,既方便了上網也沒有被封IP的問題,下面簡單介紹一下OpenWrt搭建PPTP服務的過程,本人確實感覺在OpenWrt搭建確實要比Ubuntu麻煩許多。

首先需要在路由器上安裝pptpd服務,在OpenWrt官網就能下載到,但是安裝這個ipk包需要兩個依賴,mppe和gre,其中一個比較重要的依賴是Mppe的依賴,這個依賴的安裝還需要依賴,而且依賴的依賴還需要依賴,大概能折騰4-5層的樣子,安裝了很多個ipk包才算把pptpd這個服務裝上

裝了下圖的所有包


裝上pptpd以後就可以修改相應的配置檔案了,基本套路和Ubuntu上的pptpd差不多,只不過暗藏了很多小坑

首先要修改總配置/etc/pptpd.conf檔案,這裡面主要修改的是服務端的虛擬IP地址和客戶端的虛擬IP地址,注意這兩個IP可以在同一個網段也可以在不同的網段,但是我極力推薦將他們放到同一個網段中,方便遠端DNS解析,我的配置檔案如下

#debug
option /etc/ppp/options.pptpd
speed 115200
stimeout 10
#localip & remoteip are not needed, ip management is done by pppd
ppp /usr/sbin/pppd
localip 192.168.0.1
remoteip 192.168.0.100-240
我配置的網段是192.168.0.x,如果這個與你網路環境衝突的話推薦你換個其他的網段

然後再修改使用者名稱密碼配置/etc/ppp/chap-secrets,這裡有一個大坑,使用者名稱嗎密碼中間的PROVIDER,在Ubuntu上填pptpd就好,但是在OpenWrt不能這樣填了,因為這個專案要與/etc/ppp/pptpd-options中的name欄位值一致才行,否則使用者名稱密碼不起作用

#USERNAME  PROVIDER  PASSWORD  IPADDRESS
alex       pptp-server  123456     *
alex1       pptp-server  123456     *
alex2       pptp-server  123456     *
alex3       pptp-server  123456     *
alex4       pptp-server  123456     *
alex5       pptp-server  123456     *
alex6       pptp-server  123456     *
alex7       pptp-server  123456     *
alex8       pptp-server  123456     *
alex9       pptp-server  123456     *
alex10       pptp-server  123456     *
下面就是配置最重要的一個檔案/etc/ppp/pptpd-options,我的配置如下
#debug
#logfile /tmp/pptp-server.log
auth
name "pptp-server"
lcp-echo-failure 3
lcp-echo-interval 60
default-asyncmap
mtu 1482
mru 1482
nobsdcomp
nodeflate
#noproxyarp
#nomppc
mppe required,no40,no56,stateless
require-mschap-v2
refuse-chap
refuse-mschap
refuse-eap
refuse-pap
ms-dns 192.168.0.1
#plugin radius.so
#radius-config-file /etc/radius.conf
這裡面的name欄位的值就是chap-secrets中的PROVIDER,一定要保持一致,這個檔案只需修改一處地方也是非常關鍵的一處地方,就是ms-dns欄位。這個欄位必須仔細填寫,才能實現客戶端遠端解析DNS,也就是讓客戶端將DNS請求傳送到VPN伺服器,由伺服器代理解析,否則配置不好的話客戶端會自己向自己所在網路傳送DNS請求,後果可想而知肯定被汙染的很厲害。

舉例說明:如果你ms-dns填寫8.8.8.8或者114.114.114.114等公共DNS伺服器,那麼這樣填的意義相當於一個家用路由器向接入的裝置通告DNS伺服器,客戶端會根據通告的地址向8.8.8.8或者114傳送DNS請求,此時路由器只是做一個轉發的工作,不會代理客戶端去請求。所以在VPN客戶端上,如果你通告公共DNS,客戶端傳送的DNS請求不會經過VPN服務端,而是在客戶端本地解決。我再Windows和Android裝置上測試都是如此,也就是說通告公共DNS的話是無法做到VPN伺服器遠端解析的。

如果我VPN伺服器所在內網有一臺DNS伺服器會怎麼樣呢?比如我的VPN伺服器IP為192.168.1.81,而192.168.1.2是一臺開放53埠的DNS伺服器,那麼我填寫ms-dns 192.168.1.2行不行呢。我當時覺得也應該沒什麼問題,因為我客戶端用瀏覽器訪問192.168.1.2:80的時候可以開啟192.168.1.2上的頁面,說明我向192.168.1.2傳送資料的話會發送到VPN服務端所在的內網。但事實結果卻讓人大跌眼鏡,在一臺外網Android裝置上測試的時候發現,DNS請求超時了,然後自動向Android非VPN的通告DNS伺服器傳送請求,導致Android手機IP雖然是VPN的IP,但是上網速度異常緩慢,windows直接打不開網頁。於是問題就在這,像Android這樣的裝置如果你通告一個內網的DNS伺服器IP給它,Android手機會向手機所在的內網傳送DNS請求,也就是DNS請求不傳送到VPN伺服器上去。而TCP的請求會發送到VPN上去,這就導致了雖然192.168.1.2上的80埠能訪問通,但是DNS卻超時的原因。

那麼既不能通告公網地址,又不能通告內網地址,該怎麼辦才能實現DNS的遠端解析呢。答案就是我前面提到的將VPN伺服器的虛擬ip地址和客戶端的虛擬ip地址放在同一個網段上,比如VPN服務端的ip為192.168.0.1,客戶端ip為192.168.0.2-254,然後ms-dns填寫192.168.0.1。如此一來,客戶端終於可以把DNS請求傳送到VPN服務端了,Android和Windows上測試均可用。然後我用pdnsd在服務端監聽192.168.0.1:53埠,注意這裡必須繫結192.168.0.1,然後客戶端就可以收到服務端上由pdnsd解析的防汙染DNS結果了。

部署pdnsd還有兩個大坑,第一是pdnsd在配置檔案裡寫繫結192.168.0.1然後在啟動的時候啟動失敗,說不能繫結這個埠。然後用ifconfig檢查一下發現沒有任何一塊網絡卡的地址是192.168.0.1,因為這個時候一個客戶端還沒接入呢,所以沒有ppp0,1,2...等等虛擬網絡卡,也就不能監聽192.168.0.1網段,這個時候必須有一臺裝置接入VPN製造一個ppp0網絡卡才行,接入幾個客戶端就會產生幾塊虛擬網絡卡,當然我們有一個客戶端就夠了,否則是無法開啟一個監聽192.168.0.1的服務程式的。



第二個大坑是dnsmasq,預設狀態下dnsmasq監聽的是0.0.0.0:53,理論上應該包含192.168.0.1網段,但實際上使用nslookup www.baidu.com 192.168.0.1會告訴你無法連線DNS伺服器,也就是說dnsmasq壓根就不監聽192.168.0.1:53的請求,所以後來我才單獨使用pdnsd的。而且dnsmasq不接受192.168.0.1:53的請求也就算了,它卻還佔著192.168.0.1:53這個埠,導致pdnsd無法啟動,典型的佔著茅坑不拉粑粑的行為。在Ubuntu上可以通過/etc/dnsmasq.conf指定dnsmasq的監聽地址為其他地址,而在OpenWrt上同樣的語句居然不管用。最後沒辦法只能kill掉dnsmasq服務讓pdnsd上位。但是這樣一來有非常大的缺陷就是dnsmasq管理的DHCP服務癱瘓了,導致路由器不能再做DHCP的IP分配了,別的裝置也連不上路由器了。只能通過設定固定IP地址連線路由器。如果不想連不上路由器可以修改/etc/dnsmasq.conf將埠指定到5353或者別埠上再使用/etc/init.d/dnsmasq start 才恢復DHCP服務,而且路由器此時還沒法解析DNS了,需要修改/etc/resolv.conf檔案為公共的DNS而非127.0.0.1真是麻煩呀。

如果你最終開啟了pdnsd在192.168.0.1:53,那麼遠端windows和Android裝置就可以通過VPN服務端的代理來解析IP地址了,有效防止了DNS汙染。


下面是windows客戶端的截圖,注意這裡通告的DNS要是VPN服務端的地址


然後我想啟動pptpd服務,發現又來一個坑,/etc/init.d/pptpd start 根本不管用,真是無奈,只能手動啟動了,好在手動啟動也一樣能跑,命令如下

/usr/sbin/pptpd -c /etc/pptpd.conf

然後由於我們PPTP客戶端的網段和上級路由器的網段不同,所以需要做NAT,這是搭建所有形式的VPN服務端都必不可少的一步,方法如下

iptables -t nat -I POSTROUTING -s 192.168.0.1/24 -o eth0 -j MASQUERADE

其中eth0是你可以連線外網網絡卡的名字。

然後通過netstat -nlp就能看見1723的tcp埠在監聽了。不過你以為這樣一個pptpd服務就搭建完成了麼,當然在Ubuntu上確實是這樣,而在OpenWrt上現在PPTP連線成功了但是沒法上網,還需要做一個埠對映,也就是解除防火牆對請求OpenWrt的攔截(OpenWrt預設的防火牆比Ubuntu的防火牆嚴格的多),如下特別要注意黃線標註的地方,特別是Masquerading的那個勾一定要勾上,不然雖然咱們在上面做了NAT但是仍然不能訪問公網(訪問路由器是可以的)。如果你沒有luci介面或者外網還是不能訪問1723介面,可以去看看我之前寫的一篇部落格《Openwrt 埠對映的常見問題》。


到這裡終於大功告成了,可以在外網的其他客戶端上連線這個PPTP VPN訪問內網了,如果你想知道如何將SS轉為VPN使用實現科學上網的效果,可以去找找我之前寫的部落格《Socks5代理(SS/SSH)轉國內PPTP VPN的方法》。

最後還發現很坑的一點,我使用花生殼綁在路由器上,雖然有公網地址,但是花生殼不是很穩定,經常與花生殼失聯導致域名被解析到別的地方去,讓這個VPN變得不穩。還有更坑的一點是作為一個家用的公網IP地址,運營商封了80,8080等埠,造成了很大的不方便。

你以為這些大坑到這裡就結束了?我還發現更坑的是如果你的IP是電信的,那麼移動就訪問不了,聯通和長城還可以,如果你的IP是移動的,那麼電信聯通都訪問不了,只有移動自己可以訪問,我在電信的網路想要訪問兩公里之外家裡的路由器還需要掛國外的代理繞一圈才能訪問的到,直連只有22埠能通,真實無語了。