mac mini配合linux当服务器使用

前言

我主业是安卓开发,但不务正业的我又在折腾别的了。

之前写过一篇关于 NX54 如何配置 iptables 以开放指定 IP 的 IPv6 防火墙规则。最近又把手上的一块 14 年的废弃 ARM 开发板翻出来,挂了块硬盘,让我在任意设备上都能访问家里的网络。要说这块板子,官方系统只到ubuntu 2014,连python3都没法装,之前折腾过armbian,但kernel有问题,usb不工作。最近看论坛去年有人升级了内核了,赶紧换一下系统。

过年期间家属送了一台 Mac mini(现在百亿补贴入手价 2899,血亏 600),于是我又折腾了一下,把整个网络重新整理了一遍。熬了几个夜晚和午休时间,总算弄好了,这里记录一下过程中遇到的问题和解决方案。

之前我做了什么

  1. 桥接路由,这样可以直接获取公网ipv6地址,供自己在外边连接。
  2. 关防火墙。大多数路由器都有ipv6防火墙,像我的NX54就是基于ip6tables的配置,需要关掉。我是只关掉了我的linux的ip。我使用了脚本自动更新,脚本流程如下:
    1
    linux定时任务 -> python脚本 -> 获取ipv6 -> 发现变化 -> 更新nx54防火墙 -> 更新cloudflare dns AAAA(最早做了一版发email的,后来改ddns了)
    不得不说,cloudflare真的是互联网之光,域名便宜,免费加速,还提供Pages,Workers。
  3. linux关闭ssh密码访问,把常用的设备公钥加进去。 经过上面的配置,外网只能通过IPV6访问到linux,利用SSH建立隧道,还能连接家里的电脑,方便又安全。

Mac mini准备

能源

  • ✅ 防止进入睡眠
  • ✅ 唤醒以供网络访问
  • ❌ 如有可能,将硬盘置于睡眠状态
  • ✅ 断电自动重启

远程桌面

设置 -> 通用 -> 共享 -> 屏幕共享 & 远程登录 & 文件共享
mac支持屏幕分享,但是是通过vnc://协议访问的,如果要通过ARD,那还需要花几百块买软件。平替方案:走ssh通道

1
ssh -L 5900:192.168.x.x:5900 username@linux_ipv6

command + spcae 屏幕分享 输入localhost就能连了,如此一来就是加密的。本来我是准备用wireguard去连接的,但一直没从10.0.0.0穿透到192.168.x.x,不好直接用ssh隧道更方便。

打开自动登录

1
设置 -> 用户与群组 -> 自动以此身份登录

这一项非常关键,不然重启后就卡在登录界面,需要手动输入密码。

服务开机启动

适用一些需要开机启动的服务,和linux不一样,使用launchctl管理。注意脚本不要放在Documents,没权限访问,自己在~下新建一个

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 唯一的标识符 -->
<key>Label</key>
<string>yourshell.startup</string>

<!-- 要执行的命令 -->
<key>ProgramArguments</key>
<array>
<string>/path/to/yourshell.sh</string>
</array>

<!-- 在加载时自动启动 -->
<key>RunAtLoad</key>
<true/>

<!-- 如果脚本停止,保持脚本运行 -->
<key>KeepAlive</key>
<true/>

<!-- 丢弃标准输出 -->
<key>StandardOutPath</key>
<string>/Dev/null</string>

<!-- 丢弃标准错误输出 -->
<key>StandardErrorPath</key>
<string>/Dev/null</string>
</dict>
</plist>
1
2
3
4
# 停止
sudo launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/yourshell.startup.plist
# 加载
sudo launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/yourshell.startup.plist

打通转发(linux -> Mac mini🪜)

配置

我使用 Linux 网关配合 MosDNS 进行 DNS 分流:直连流量不处理,访问内部网站解析虚拟ip,然后通过 iptables 进行路由转发。由于 Mac 不支持 TPROXY,所以我在 Mac 上运行 SOCKS 代理,然后在 Linux 上使用 TPROXY 转发连接到 SOCKS。

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
# 修改iptables
iptables -t mangle -N MYWAY 2>/dev/null
iptables -t mangle -F MYWAY
iptables -t mangle -A MYWAY -d 198.18.0.0/16 -p tcp -j TPROXY --on-port <tproxy_port> --tproxy-mark 1
iptables -t mangle -A MYWAY -d 198.18.0.0/16 -p udp -j TPROXY --on-port <tproxy_port> --tproxy-mark 1
iptables -t mangle -D PREROUTING -j MYWAY 2>/dev/null
iptables -t mangle -A PREROUTING -j MYWAY

# 开启NAT转发
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.conf.all.route_localnet=1" | sudo tee -a /etc/sysctl.conf
sysctl -p

# nat转换 注意这里区分你的网络接口
iptables -t nat -A POSTROUTING -o end0 -j MASQUERADE

# 路由 注意这两条也要保存到rc.local,不然重启后就失效了。
ip rule add fwmark 1 lookup 100
ip route add local 0 0.0. 0/0 dev lo table 100

# 保存 iptables配置
sudo iptables-save | sudo tee -a /etc/iptables/rules.v4
sudo nano /etc/rc.local
# 添加 iptables-restore < /etc/iptables/rules.v4
# 添加 ip rule add fwmark 1 lookup 100
# 添加 ip route add local 0 0.0. 0/0 dev lo table 100
# 保存

# 确保有执行权限
sudo chmod +x /etc/rc.local

最终实现的效果如下:

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
📱 手机(或其他设备)

├── 发起请求(例如:访问 https://www.example.com)

├── 📡 DNS 请求发送至 ➜ 192.168.x.115(网关设备上的 MosDNS)

│ └─ MosDNS 分流:
│ ├─ 直连域名 → 直连(返回真实 IP)
│ └─ 内部域名 → 发给 113 上的 DNS服务

│ └─ DNS服务 返回 fake-ip(如 198.18.0.x)

└── 手机收到 fake-ip(例如 198.18.0.33)后发起连接

发出 TCP 请求目标:198.18.0.33:443

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🛡️ 网关设备(115)iptables 检测

├── mangle 表匹配到 fake-ip 段(198.18.0.0/16)

├── TPROXY 重定向流量 → 本地转换服务

├── 路由策略:
│ └─ fwmark=1 → local via lo(回送至本地转换服务

└── 本地转换服务 接收到TPROXY流量

转发至 代理服务(113)的 Socks 服务
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🧱 代理服务(113)处理流量

└── 访问目标网站(如 example.com),建立 TLS 连接

返回响应
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⬆️ 回程流量返回手机,访问完成

踩过的坑

有些细节不说了,我还有份详细的笔记,但不方便暴露。这里走了点弯路,踩坑总结:

  1. tproxy to socks 本来尝试用工具redsocks,AI说不支持udp,放弃了。改用另一款,性能稍微差点,但支持的协议多,配置也简单。
  2. 一定要配echo "net.ipv4.conf.all.route_localnet=1" | sudo tee -a /etc/sysctl.conf 这一项才允许路由lo,我本身对linux的网络熟练度低,就因为这个配置,搞了好久,AI也一直没讲,后面一点点查到的。
  3. 起初直接使用 TUN 实现,毕竟是个虚拟网卡,招呼了所有流量,后来觉得不够优雅,最终改成 DNS分流 + TPROXY + SOCKS,感谢一位哥们跟我交流后确定了方向。
  4. 为什么非要建在mac上,因为开发板性能太差,虽然还能撑,但能少安服务就少安吧,况且在新mac上加一个这个服务跑,完全不受影响。我在linux上面还有个Alist(板子原生支持SATA,就接了块电脑硬盘)。
  5. linux上有个systemd-resolved,记得disable,占了53端口。当然也可以不做,需要设备上指定DNS端口。

居然是冰的

Mac mini跑好几天了,摸一摸表面居然是冰的。家里养猫,PDD 26买了个3D打印的底座,不是15块那个,不是一个做工。