Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

有一天,因為要著手開發,剛好我工作站重裝了,所有各個軟件的代理配置都沒有去備份,想著我設備太多了,也是時候需要在家的路由上做個代理了。這個計畫一直因為沒有時間所以拖了很久。雖然家裡也有一個已經配置好的 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
# 如果結果為 1 ,就是打開了,那接下來不需要操作
sysctl net.ipv4.ip_forward

# 臨時打開一下
sysctl -w net.ipv4.ip_forward=1
# 可以使用文本編輯工具增加這個配置到自己系統的 sysctl.conf 或者等價配置文件內
# 我這裡是 /etc/sysctl.d/02-net.conf
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

1
apt install bind -y

然後配置 /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

#
# Origin - https://moe.best/tutorial/overture.html
#

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

# 所有到 Shadowsocks 的連接全部直連, 假設代理服務器是 114.51.4.19 端口 19810
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
# 內網連接全部 pass
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
# 中國連接也 pass
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-saveipset save 保存好 iptables 和 ipset 的配置,不然重啓關機又要手動配置一次。可以寫個 service 自動開機的時候 restore 回去。

一開始一點都不懂,現在懂了一點點,然後就這樣做了這個路由器 + 代理。匆忙寫下來怕日後忘記。

x86 的話,這個方案還有很多可以擴展的地方,例如軟件本身的配置優化、增加分流選項、自動更新 ip 和域名列表⋯⋯ 這些都是等以後再搞了。

接下來有時間,可能還會嘗試重新做一套能在 openwrt 上運行的方案。

评论