有一天,因為要著手開發,剛好我工作站重裝了,所有各個軟件的代理配置都沒有去備份,想著我設備太多了,也是時候需要在家的路由上做個代理了。這個計畫一直因為沒有時間所以拖了很久。雖然家裡也有一個已經配置好的 pdm 固件的路由器,但裡面的設定都是 ASUS 固件專屬,加上其性能比較差,而且是我隨身用的,就不方便做家裡的路由器。
現在我附近比較流行和普遍的代理軟件一般就是 Shadowsocks, 雖然有些朋友比較高級用 IPsec 解決問題,但畢竟我不是專門搞網絡的,就用身邊有的東西吧。
我用的解決方案是 iptables + ipset + shadowsocks 做自動分流, dhcpd 作 DHCP 服務器, bind + overture 作 DNS 解釋。 DNS 解釋用 bind 是因為我還需要在局域網裡部署一個 LAN 專用的 DNS 解釋,以及想嚐鮮。overture 是網友介紹的,說實現我的目的的話能省點事,而且 x86 路由不需要考慮存儲空間問題( 這個 Golang 寫的 DNS 代理解釋服務體積上到 20M + ,有點龐大了)。
接下來的操作建議直接在真機上操作,並直接 sudo su
進入管理員權限以省去頻繁鑑權的麻煩。
NAT 配置 我的機器是擁有四個獨立網卡的 i5 ,系統是 AOSC OS 5.0 ,但只要是 Debian 系的,這個設置方法都能用。
四個網卡分別是 enp1s0 - enp4s0 。我使用 enp1s0 作為 WAN 接外網,外面接一個 Mikrotik 撥號,暫時不搞 ppp 撥號了。其餘的網卡作為 LAN 使用。
首先確認 iptables 工具集存在,能使用 iptables 命令修改防火牆。然後,打開內核的網絡轉發功能
1 2 3 4 5 6 7 8 sysctl net.ipv4.ip_forward sysctl -w net.ipv4.ip_forward=1 echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/02-net.conf
nmtui 配置網絡設備 系統使用 NetworkManager 管理網絡,下面我就直接在 nmtui 內操作了。
enp1s0 對應的配置不需要修改,默認 DHCP 獲取 IP 和網絡設置就行。
接下來新增一個橋設備,把所有其他的網卡橋接在一起。
在 IPv4 選項,填上你喜歡的路由器 IP 地址和子網掩碼,例如默認的 192.168.1.1/24 (=192.168.1.1 255.255.255.255)。
之後選擇 Add ,逐個添加 Ethernet slave 就好。 Device 填上網卡設備名。
配置好之後就不用其他東西了,出去前檢查一下 Automatically connect 都勾上了沒。
這樣,我們就有了一個 WAN 口和三個 LAN 口了,接下來需要在 iptables 上調整讓內核作 NAT 工作。
iptables 配置 NAT 我本人對防火牆配置很不熟悉,所以就照葫蘆畫瓢就好了。
1 2 3 4 # 從 nm-bridge(也就是 LAN )來的包轉發都允許 iptables -t filter -A FORWARD -i nm-bridge -j ACCEPT # 不知道什麼東西,大概就是從 enp1s0 出去的都 MASQUERADE 方式處理 iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
然後就行了,現在這個機子就變成路由器了。接到 LAN 口們的設備,只要設置好 ip 、子網掩碼和路由器 IP 就能上網了。
DHCP 配置 接下來的軟件不一定要用 Systemd 來控制,只要知道配置文件位置,直接運行也可。
畢竟這個是通過 Systemd 精準控制的路由器,所以我肯定是要用 Systemd 管理接下來的各種軟件啦。(大霧)
我系統內的 dhpc 服務器 service unit 是 dhcpd-ipv4
首先需要配置一下 dhcpd.conf 配置,我的配置位置在 /etc/dhcp/dhcpd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 域名稱和域的域名服務器,這個自己隨便吧。 option domain-name "cattenlinger_hut.lan"; option domain-name-servers ns.cattenlinger_hut.lan; # 續租時間 default-lease-time 3600; max-lease-time 7200; # 分配的 dhcp 段,填上路由器所在的網段即可 subnet 192.168.114.0 netmask 255.255.255.0 { option routers 192.168.114.1; option subnet-mask 255.255.255.0; option domain-search "cattenlinger_hut.lan"; option domain-name-servers 192.168.114.1; # 範圍 range 192.168.114.100 192.168.114.240; }
保存好之後,systemctl enable dhcpd-ipv4 --now
即可現在立馬原地開始並開機啟動(x
現在,內網中的電腦不需要手動設置即可 DHCP 自動分配地址上網了(不過不知道為什麼我實際使用的時候 dhcp 的反應很慢),但因為還沒設置域名解析服務,所以還不能通過路由器解釋域名。
Bind 域名解析服務 先安裝 bind
然後配置 /etc/named.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 // Access control list ,建議配置一下僅允許內網訪問。 acl allowed_clients { // 允許所有本地請求 127.0.0.0/24; // 允許所有內網請求 192.168.0.0/16; }; // 這裡只配置域名緩存和解釋轉發,所以只需要使用最基本配置 options { // 工作目錄和 pid 文件 directory "/var/named"; pid-file "/run/named/named.pid"; // 監聽內網和本地 listen-on { 192.168.114.1; 127.0.0.1; }; // 轉發給誰解析 forwards { // Cloudflare //1.1.1.1; // Google //8.8.8.8; //8.8.4.4; // Open DNS //208.67.222.222; //208.67.220.220; // Alibaba DNS //223.6.6.6; //223.5.5.5; // Plain old 114 DNS //114.114.114.114; // Local DNS Proxy 127.0.0.1 port 2053; }; // 這個設置有兩個選項, only 和 first。 // only 代表只轉發不緩存 // first 代表如果轉發目的服務器無法獲得結果,則使用本地緩存 forward first; }
如果關掉 Local DNS Proxy 選項,直接啟動上面的 DNS 服務器,就能現在通過路由器轉發解釋出去了。不過接下來還得配置 DNS 解釋代理所以我就先只留下代理的地址了。
systemctl enable bind --now
即可立馬享受 DNS 服務且開機自啟動。
Shadowsocks 雖然 Shadowsocks 配置已經爛大街,不過這裡也稍微再囉嗦一下好了。
如果是 Ubuntu ,直接 apt install shadowsocks-libev -y
就行了,而且其帶上對應的模板服務可多配置啟動。在 /etc/shadowsocks-libev
內配置 對應的 config ,然後 systemctl enable shadowsocks-libev-redir@config-name --now
即可。
我這裡的不帶 service ,就自己寫了個。
啟動好之後就行了,不用管什麼。但建議同時開啟一個 ss-redir 一個 ss-local ,方便之後的 DNS 解釋使用。
Overture Overture 的 Github 主頁
使用比較簡單,啟動即可。不過建議稍微更改一下配置文件、填充 IP 和域名列表。
這裡貼出我的配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 { "BindAddress" : ":2053" , "DebugHTTPAddress" : "127.0.0.1:5555" , "PrimaryDNS" : [ { "Name" : "Alibaba DNS" , "Address" : "223.6.6.6:53" , "Protocol" : "udp" , "SOCKS5Address" : "" , "Timeout" : 6 , "EDNSClientSubnet" : { "Policy" : "auto" , "ExternalIP" : "" , "NoCookie" : true } } ] , "AlternativeDNS" : [ { "Name" : "OpenDNS" , "Address" : "208.67.222.222:443" , "Protocol" : "tcp" , "SOCKS5Address" : "127.0.0.1:1080" , "Timeout" : 6 , "EDNSClientSubnet" : { "Policy" : "auto" , "ExternalIP" : "" , "NoCookie" : true } } ] , "OnlyPrimaryDNS" : false , "IPv6UseAlternativeDNS" : false , "WhenPrimaryDNSAnswerNoneUse" : "PrimaryDNS" , "IPNetworkFile" : { "Primary" : "/opt/software/overture/ip_network_primary_sample" , "Alternative" : "/opt/software/overture/ip_network_alternative_sample" } , "DomainFile" : { "Primary" : "/opt/software/overture/domain_primary_sample" , "Alternative" : "/opt/software/overture/gfw_all_domain.txt" } , "HostsFile" : "/etc/hosts" , "MinimumTTL" : 0 , "DomainTTLFile" : "/opt/software/overture/domain_ttl_sample" , "CacheSize" : 0 , "RejectQType" : [ 255 ] }
詳細的配置可以參考一下官方文檔。我這裡程序和配置路徑都是 /opt/software/overture ,所以就把裡面的文件地址都寫成絕對的了。方便通過 systemd 啟動。
PrimaryDNS 和 AlternateDNS 分別是兩個不同的 DNS 服務器, Overture 通過接下來的 Primary 和 Alternative 配置分別作不同的解析操作。優先使用 Primary ,然後再 Alternative 。一般都是把 Primary 配置成國內的 DNS 解釋服務,然後 Alternative 配置為國外的。配置內給出的是 OpenDNS 的 DNS over HTTPS ,然後通過開在 1080 端口上的 ss-local 代理訪問。這樣就能實現 DNS 出國查詢了。
IPNetworkFile 以及 DomainFile 獲取 比較需要關注的兩個文件,IPNetworkFile 內的 Primary 和 DomainFile 內的 Alternative 。
第一個文件,直接填上整個中國的網段列表即可。
第二個文件,填上 GFW 列表即可。
網段列表來源有兩個,GeoLite 或者是 APNIC ,可以運行下面的腳本從 APNIC 獲取中國網段。
1 2 3 #!/bin/bash URL='http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' curl "$URL " | grep ipv4 | grep CN | awk -F\| '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > china.list
GeoLite 的話,從 MaxMind 這個連接 下載後,自己 grep + awk 提煉出來也可以 w ,文件格式很簡單。有了這個甚至能實現不同國家走不同的代理。不過我在這裡就不多寫了。
GFW 列表的獲取,我是看的這篇文章 。這裡貼出腳本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #!/bin/bash curl https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt \ | base64 -d \ | sort -u \ | sed '/^$\|@@/d' \ | sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' \ | sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /qq\.com/d' \ | sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' \ | grep '^[0-9a-zA-Z\.-]\+$' \ | grep '\.' \ | sed 's#^\.\+##' \ | sort -u \ > /tmp/temp_gfwlist.txt curl https://raw.githubusercontent.com/hq450/fancyss/master/rules/gfwlist.conf \ | sed 's/ipset=\/\.//g; s/\/gfwlist//g; /^server/d' \ > /tmp/temp_koolshare.txt cat /tmp/temp_gfwlist.txt /tmp/temp_koolshare.txt \ | sort -u \ > gfw_all_domain.txt
原來的文章內也有 Overture 的相關說明,可以參照。
接下來,寫個 OvertureDNS.service
然後丟到 /lib/systemd/system
內,重加載 unit 後啟動即可。現在就能享受到一個路由和一個正常的 DNS 了。
ipset 自動出國 接下來配置自動根據 IP 所屬地確定使用代理還是直連。
ipset 配置 首先安裝 ipset , apt install ipset -y
。
然後在 ipset 創建一個集合,存放中國網段。我這裡就叫這個集合 net_list_cn
。
1 ipset create net_list_cn hash :net
然後把所有的中國 ip 丟進去就好了,可以直接利用之前 Overture 的 IP 列表。
1 IFS=$'\n' ; for i in $(cat china.list); do ipset add net_list_cn $i ; done
是個十分低效的辦法呢。。。算了能用就行了。
iptables 配置 iptables 配置繼續照葫蘆畫瓢,炒了 shadowsocks 的說明然後加點料。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 iptables -t nat -N router_auto_proxy iptables -A router_auto_proxy -d 114.51.4.19/32 -p tcp -m tcp --dport 19810 -j RETURN iptables -A router_auto_proxy -d 114.51.4.19/32 -p udp -m udp --dport 19810 -j RETURN iptables -A router_auto_proxy -d 0.0.0.0/8 -j RETURN iptables -A router_auto_proxy -d 10.0.0.0/8 -j RETURN iptables -A router_auto_proxy -d 127.0.0.0/8 -j RETURN iptables -A router_auto_proxy -d 169.254.0.0/16 -j RETURN iptables -A router_auto_proxy -d 172.16.0.0/12 -j RETURN iptables -A router_auto_proxy -d 192.168.0.0/16 -j RETURN iptables-A router_auto_proxy -d 224.0.0.0/4 -j RETURN iptables -A router_auto_proxy -d 240.0.0.0/4 -j RETURN iptables -A router_auto_proxy -m set --match-set net_list_cn dst -j RETURN iptables -A router_auto_proxy -p tcp -j REDIRECT --to-ports 9527 iptables -A PREROUTING -p tcp -j router_auto_proxy
至此,完事。。。
後記 記得通過 iptables-save
和 ipset save
保存好 iptables 和 ipset 的配置,不然重啓關機又要手動配置一次。可以寫個 service 自動開機的時候 restore 回去。
一開始一點都不懂,現在懂了一點點,然後就這樣做了這個路由器 + 代理。匆忙寫下來怕日後忘記。
x86 的話,這個方案還有很多可以擴展的地方,例如軟件本身的配置優化、增加分流選項、自動更新 ip 和域名列表⋯⋯ 這些都是等以後再搞了。
接下來有時間,可能還會嘗試重新做一套能在 openwrt 上運行的方案。