menu Chancel's blog
rss_feed
Chancel's blog
有善始者实繁,能克终者盖寡。

R2S刷入Armbian指南

作者:Chancel Yang, 创建:2024-04-21, 字数:13102, 已阅:147, 最后更新:2024-04-21

1. R2S

R2S是一台优秀的迷你Arm服务器,其功耗低、双千兆以及价格低的优势,让这个设备非常流行,关于R2S的系统设置教程也非常多

大部分R2S的教程都是刷入openwrt,这是实现透明代理网关比较低成本的方案,但无论是openwrt还是其他第三方路由系统,对我而言始终不如Armbian这种原生Linux系统来的有吸引力

Armbian也可以非常完美的实现透明代理网关,且设置起来不像openwrt一样,在Web界面上又繁琐又复杂,还经常找不到设置选项在哪里

使用R2S+Armbian来实现类openwrt的效果,其思路与之前的文章Linux透明网关思路一致,本文可以看成是R2S版的透明网关实现,其网络拓补图如下:

在上图中,我省略了光猫的部分,R2S将取代原来路由器的位置,2个千兆接口分别接入路由器的WAN口和光猫拨号LAN口

R2S负责宽带拨号以及网络转发、网络分流的功能,这一点与openwrt版的R2S是一模一样的

下面将一步一步地实现拨号、DNS解析以及针对不同IP分别处理直连与科学代理

2. Armbian

Armbian是一个基于Linux的操作系统发行版,专门为ARM架构的单板计算机(如树莓派、Orange Pi等)设计和优化,也包括了R2S,可以从Armbian的官网上下载得到属于R2S的Armbian系统镜像

2.1. 系统安装

R2S的官方镜像地址

下载后的系统镜像是一个.xz文件,无需解压.xz,直接将镜像写入到内存卡上即可

  • Linux可以使用dd直接写入
  • Windows推荐使用Rufus写入

写入内存卡后,将内存卡插入R2S中,再接入电源和网线,并观察WAN/LAN灯是否亮起,接着登录路由器后台,查看R2S被分配到的IP,之后使用SSH远程登录

  • 账户:root
  • 密码:1234

登录后会提示你进行初始化设置,包括ROOT账户密码以及一个具备管理员权限的账户

2.2. 系统设置

如果访问外网不畅通,可以将Armbian的源更换到清华源

安装要用的一些必要软件以及我的一些常用软件

Bash
# 更新软件包
apt update -y
# 更新系统
apt upgrade -y
# 安装必要软件
apt install -y supervisor gcc make iproute2 ipset pppoeconf vim wget git curl unzip dnsutils net-tools tree
# 安装我常用的软件(可选)
apt install -y btop proxychains openssl

此外,Armbian也支持sudo权限管理,如果有用户设置的需求,请自行编辑sudo文件进行权限分配,以下默认采用Root用户进行操作

2.3. 宽带拨号

在初始化后,将R2S的LAN口设置为静态IP,编辑:/etc/netplan/armbian-default.yaml

YAML
network:
  version: 2
  renderer: NetworkManager
  ethernets:
    lan0: # 请确保你的LAN口名称是lan0
      dhcp4: no
      addresses: [192.168.2.1/24]
    eth0: # 请确保你的WAN口名称是eth0
      dhcp4: yes
      nameservers:
        addresses: [114.114.114.114]

然后将R2S的LAN口接入路由器,将WAN口接入光猫,将路由器设置为:

  • 静态IP:192.168.2.1
  • 静态网关:192.168.1.1
  • 静态DNS服务:192.168.1.1

接着使用ssh会话连接到192.168.2.1,即你的R2S,再进行宽带拨号

Bash
pppoeconf

根据提示填入宽带帐号密码即可,拨号成功后,需要将来自LAN口的流量转发给WAN口处理

编辑:/etc/sysctl.conf

Bash
...
# 允许IPV4的流量转发
net.ipv4.ip_forward=1

更新IP转发的设置

Bash
sysctl -p

添加转发规则

Bash
iptables -t nat -A POSTROUTING -j MASQUERADE

在局域网内,使用任意设备通过ping 114.114.114.114确认网络是否畅通

3. 透明代理网关

网络透明代理(Transparent Proxy)是一种网络代理的方式,在代理服务器和用户之间进行中间层的数据传输,而对用户来说,它是透明的,用户无需进行任何额外的配置

这种代理方法广受好评,不用在每一个设备上反复的安装代理软件,对于一些游戏机、特定系统的设备来说也非常友好,这也是openwrt以及第三方路由系统广受欢迎的原因

3.1. 透明代理(Gost)

代理我使用的是gost,服务端的部分可以使用商业代理或者自建服务器,这里假设代理协议是ss

下载gost:

下载到/root/gost/中,解压后目录如下

Bash
nanopi-r2s:gost:# tree                                                      
.
├── gost
├── gost_3.0.0-rc8_linux_arm64.tar.gz
├── LICENSE
├── README_en.md
└── README.md

0 directories, 5 files

编辑:/root/gost/config.yml

YAML
services:
- name: "18080"
  addr: :18080 # 用于DNS代理向Google DNS服务器进行查询的端口
  handler:
    type: auto
    chain: chain-0
  listener:
    type: tcp

- name: "28080"
  addr: :28080 # RED是透明代理接口,具体可参考Gost官网说明
  handler:
    type: red
    chain: chain-0
  listener:
    type: red


chains:
- name: chain-0
  hops:
  - name: hop-0
    nodes:
    - name: "[代理服务器IP]"
      addr: "[代理服务器IP]:[端口]"
      connector:
        type: ss
        auth:
            username: [代理协议]
            password: [代理协议的密码]

根据你的ss协议,自行修改上述4个代理配置位置,然后运行gost服务进行测试

Bash
/root/gost/gost -C /root/gost/config.yml

另开一个SSH会话,进行代理协议测试

Bash
export http_proxy=http://127.0.0.1:18080
export https_proxy=http://127.0.0.1:18080

# 测试应输出你代理服务器的IP
curl cip.cc

验证没有问题后,将gost添加到supervisor的后台运行列表

编辑:/etc/supervisor/conf.d/gost.ini

INI
[program:gost]
command=/root/gost/gost -C /root/gost/config.yml
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
stdout_logfile_maxbytes=20MB
stdout_capture_maxbytes=1MB
user=root

更新supervisor运行,并检查运行状态

Bash
supervisorctl update
supervisorctl status

3.2. DNS解析(Overture)

配置R2S解决DNS污染,这里借助overture来处理国内DNS污染

overture仓库地址:

  • https://github.com/shawn1m/overture/releases

由于R2S的Armbian系统自带DNS服务systemd-resolved.service,需要先将其禁用

Bash
systemctl stop systemd-resolved.service
systemctl disable systemd-resolved.service

在禁用掉自带的DNS服务后,下载后(V1.8版本)到/root/overture中解压,目录输出如下:

Bash
nanopi-r2s:overture:# tree
.
├── config.yml
├── domain_alternative_sample
├── domain_primary_sample
├── domain_ttl_sample
├── hosts_sample
├── ip_network_alternative_sample
├── ip_network_primary_sample
├── overture-linux-arm64
└── overture-linux-arm64.zip

0 directories, 9 files

编辑:/root/overture/config.yml

YAML
bindAddress: :53
debugHTTPAddress: 127.0.0.1:55555
dohEnabled: false
# 国内域名DNS服务器
primaryDNS:
  - name: DNS114
    address: 114.114.114.114:53
    protocol: udp
    socks5Address: 
    timeout: 6
    ednsClientSubnet:
      policy: disable
      externalIP:
      noCookie: true
onlyPrimaryDNS: false
# 国外域名DNS服务器
alternativeDNS:
  - name: GoogleDNS
    address: 8.8.8.8:53
    protocol: tcp
    socks5Address: 127.0.0.1:18080 # Google DNS 服务器可以通过代理访问,这里的代理是上一步gost中设置的
    timeout: 6
    ednsClientSubnet:
      policy: disable
      externalIP:
      noCookie: true
ipv6UseAlternativeDNS: false
alternativeDNSConcurrent: false
whenPrimaryDNSAnswerNoneUse: primaryDNS
ipNetworkFile:
  primary: /root/china_ip_list.txt # 国内IP段,如匹配到则优先返回primary中的DNS服务器解析结果
  alternative: /root/overture/ip_network_alternative_sample
domainFile: 
  primary: /root/overture/domain_primary_sample
  alternative: /root/gfw_all_domain.txt # 国外GFW域名列表,识别到是被关照的域名则优先采用alternative中DNS服务器解析结果
  matcher: full-map
hostsFile:
  hostsFile: /etc/hosts
  finder: full-map
minimumTTL: 0
domainTTLFile: /root/overture/domain_ttl_sample
cacheSize: 100
cacheRedisUrl:
cacheRedisConnectionPoolSize:
rejectQType:
  - 255

配置中重要的4个部分已添加了注释,配置中使用到的国内IP与国外域名来源:

由于china_ip_list.txtgfw_all_domain.txt文件都是需要定期更新,所以写一个脚本来实现

编辑:/root/overture_init.sh

Bash
#/bin/bash
#author:Chancel.Yang
#date:2023/09/21

wget https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt
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 > temp_gfwlist.txt
curl https://raw.githubusercontent.com/hq450/fancyss/master/rules/gfwlist.conf | sed 's/ipset=\/\.//g; s/\/gfwlist//g; /^server/d' > temp_koolshare.txt
cat temp_gfwlist.txt temp_koolshare.txt | sort -u > gfw_all_domain.txt
rm -f temp_gfwlist.txt temp_koolshare.txt

/root下执行该脚本会产生china_ip_list.txtgfw_all_domain.txt2个文件,如下:

Bash
nanopi-r2s:~:# tree -L 1
.
├── china_ip_list.txt
├── gfw_all_domain.txt
├── overture_init.sh
├── iptables.sh
└── overture

1 directory, 4 files

此时,运行overture

Bash
./overture-linux-arm64 -c ./config.yml

借助dig程序来验证是否能够顺利进行DNS解析

Bash
➜  dig www.github.com @127.0.0.1

; <<>> DiG 9.18.4 <<>> @127.0.0.1 www.github.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8772
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;www.github.com.                        IN      A

;; ANSWER SECTION:
www.github.com.         1552    IN      CNAME   github.com.
github.com.             60      IN      A       192.30.255.113

;; Query time: 243 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Tue Jul 26 18:46:44 CST 2022
;; MSG SIZE  rcvd: 107

利用supervisor设置overture为daemon后台程序

编辑:/etc/supervisor.d/overture.ini

INI
[program:overture]
command=/root/overture/overture-linux-arm64 -c /root/overture/config.yaml
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
stdout_logfile_maxbytes=20MB
stdout_capture_maxbytes=1MB
user=root

更新supervisor运行,并检查状态

Bash
supervisorctl update
supervisorctl status

3.3. 网络分流(iptables)

在完成gost与overture设置后,进行最后一步设置,将进入R2S的流量分流,将国内IP的流量直接发出去,国外IP的流量走ss协议代理出去

编辑:/root/iptables.sh

Bash
#/bin/bash
#author:Chancel.Yang
#date:2023/09/21

/usr/sbin/ipset -N china hash:net

# china_ip_list.txt文件在overture中已经下载
for i in $(cat /root/china_ip_list.txt ); 
do
    /usr/sbin/ipset -A china $i; 
done

# 创建一个NAT规则集`SSNAT`
/sbin/iptables -t nat -N SSNAT
# 符合国内IP列表的则直接转发出去
/sbin/iptables -t nat -A SSNAT -p all -m set --match-set china dst -j RETURN
# 局域网以及一些常见网段也选择直接转发
/sbin/iptables -t nat -A SSNAT -d 0.0.0.0/8 -j RETURN
/sbin/iptables -t nat -A SSNAT -d 10.0.0.0/8 -j RETURN
/sbin/iptables -t nat -A SSNAT -d 127.0.0.0/8 -j RETURN
/sbin/iptables -t nat -A SSNAT -d 169.254.0.0/16 -j RETURN
/sbin/iptables -t nat -A SSNAT -d 172.16.0.0/12 -j RETURN
/sbin/iptables -t nat -A SSNAT -d 192.168.0.0/16 -j RETURN
/sbin/iptables -t nat -A SSNAT -d 224.0.0.0/4 -j RETURN

# 将剩下IP段(国外)的tcp、udp、icmp的流量全部转发到gost的透明代理网口28080中,即被代理出去了
/sbin/iptables -t nat -A SSNAT -p tcp -j REDIRECT --to-port 28080
/sbin/iptables -t nat -A SSNAT -p udp -j REDIRECT --to-port 28080
/sbin/iptables -t nat -A SSNAT -p icmp -j REDIRECT --to-port 28080

# 最后将所有进入R2S的数据包转入`SSNAT`规则集合中
/sbin/iptables -t nat -A PREROUTING -p tcp -j SSNAT

# 将出站数据包的源地址进行NAT,否则在部分网络场景下会100%丢包
/sbin/iptables -t nat -I POSTROUTING -j MASQUERADE

此时,/root目录如下

Bash
nanopi-r2s:~:# tree -L 1
.
├── china_ip_list.txt
├── gfw_all_domain.txt
├── hosts
├── ip_domain_update.sh
├── iptables.sh
└── overture

1 directory, 5 files

借助crontab设置脚本开机自动执行

Bash
crontab -e

# 在crontab界面中添加开机运行iptables.sh脚本
...
@reboot /bin/sh /root/iptables.sh

设置完毕后,重启R2S

3.4. 网络测试

打开R2S的SSH会话,查看iptables的nat表,参考如下:

Bash
chancel@nanopi-r2s# iptables -L -n -v -t nat 
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 5371  341K SSNAT      tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
10260 1026K MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain SSNAT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
 2530  171K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set china dst
    0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/8           
    3   120 RETURN     all  --  *      *       0.0.0.0/0            10.0.0.0/8          
    0     0 RETURN     all  --  *      *       0.0.0.0/0            127.0.0.0/8         
    0     0 RETURN     all  --  *      *       0.0.0.0/0            169.254.0.0/16      
    0     0 RETURN     all  --  *      *       0.0.0.0/0            172.16.0.0/12       
  234 14040 RETURN     all  --  *      *       0.0.0.0/0            192.168.0.0/16      
    0     0 RETURN     all  --  *      *       0.0.0.0/0            224.0.0.0/4         
 2604  156K REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 28080
    0     0 REDIRECT   udp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 28080
    0     0 REDIRECT   icmp --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 28080

再检查gost与overture的运行日志是否有异常

  • /var/log/supervisor/gost.log
  • /var/log/supervisor/overture.log

最后,使用任意连入WI-FI的诣东设备访问下google/baidu观察下加载速度,验证是否成功分流

4. 尾语

相对而言,设置透明网关代理比刷入openwrt的设置要难不少,要掌握的基础知识也要多不少

但用起来会相对openwrt放心一些,没有太多的第三方野包以及难以控制的底层代码漏洞


[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
gravatar
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]