id: 05caaa3d8fc34ca4ba6d045540ade2ea
parent_id: 
item_type: 1
item_id: 8d03c71bba754985ab02876771a7ef98
item_updated_time: 1764365029762
title_diff: "[{\"diffs\":[[1,\"虚拟 openwrt 随身携带的梯子\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":18}]"
body_diff: "[{\"diffs\":[[1,\"<html>\\\r\\\n<head>\\\r\\\n  <title>虚拟 openwrt: 随身携带的梯子</title>\\\r\\\n  <basefont face=\\\"微软雅黑\\\" size=\\\"2\\\" />\\\r\\\n  <meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html;charset=utf-8\\\" />\\\r\\\n  <meta name=\\\"exporter-version\\\" content=\\\"YXBJ Windows/608924 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;\\\"/>\\\r\\\n  <style>\\\r\\\n\\tbody, td {\\\r\\\n\\t  font-family: 微软雅黑;\\\r\\\n\\t  font-size: 12pt;\\\r\\\n\\t}\\\r\\\n  </style>\\\r\\\n</head>\\\r\\\n<body>\\\r\\\n<a name=\\\"11513\\\"></a>\\\r\\\n<h1>虚拟 openwrt: 随身携带的梯子</h1>\\\r\\\n\\\r\\\n<div><span><div style=\\\"-evernote-webclip:true\\\"><br/><div><div><div><div><h1>虚拟 openwrt: 随身携带的梯子</h1><div><div></div></div></div>\\\n<div>\\\n\\\n<span>\\\n\\\n\\\n<a href=\\\"https://icymind.com/virtual-openwrt/#comments\\\" target=\\\"_blank\\\">\\\n<span>20 Comments</span>\\\n</a>\\\n</span>\\\n</div>\\\n\\\n\\\n<h3>update-2017-07-13: 用 electron 封装了虚拟机: <a href=\\\"https://github.com/icymind/VRouter\\\" target=\\\"_blank\\\">vrouter</a></h3><p>“有哪些东西你用了之后就回不去了?”</p>\\\n<p>kcptun 是我的答案之一. </p>\\\n<p>广州电信 50M 光纤 , 纯粹用 shadowsocks 的话 , 看看资本主义的网页速度勉勉强强 , 视频什么就别想了. 但是搭配上 kcptun , 上网高峰期放 1080P 都没问题. 唯一的问题是 kcptun 性能消耗有点大, 在网件 WNDR4300 上部署, 一看视频路由器的 CPU 占用率就会飙到 100% , 而且速度比桌面端的 kcptun 差几倍.</p>\\\n<p>解决方法挺多, 土豪出门右转上狗东买个旗舰路由, Geek 在路由下再挂个树莓派跑 kcptun , 实用者在桌面端用 cow 做智能代理.</p>\\\n<p>智能代理其实也不错, 但是透明代理更佳, 谁用谁知道. 在透明代理下, 终端是完全感觉不到墙得存在的, 墙是什么? 能吃吗? 不连家里 openwrt 的 Wi-Fi 时, 我就用智能代理, 但是有些终端软件它不走系统代理, 有些软件只走 http 代理, 在这些情况下, 只能一个个去明确代理. 以前用 shadowsocksX 时, 系统自带的邮件应用就没法连接 Google, npm/docker/brew也需要指定代理.</p>\\\n<p>不(mei)想(qian) 买 surge 之类的软件, 于是鼓捣了这么一个东西: virualbox 里的 openwrt, 用这个虚拟路由器接管宿主的所有流量, 在虚拟路由里做透明代理. 这样就相当绑了一个 openwrt 路由在电脑上, 无论接入什么网络, 都可以访问资本主义网站. 而且自由度比 surge 之类的要高, 毕竟直接扔了一个 linux 给你啊喂. 想用什么工具链在 openwrt 里搞就行了, 还不用担心这个路由器的性能不够. 当然比起土豪的实体路由还是逊色一点, 毕竟虚拟路由只能自己使用(或者在笔记本上再接一个实体路由, 供其他设备连接?).</p>\\\n<p>让 virtualbox 里的 openwrt 接管宿主的流量, 需要给虚拟机配两张网卡:</p>\\\n<ol>\\\n<li>一张网卡设置为桥接. 虚拟机通过这张网卡从上级路由获取 IP , 摇身变为和宿主同等的网络设备.</li>\\\n<li>另一张设为 Host-only, 宿主的网络数据从这张网卡流向虚拟路由.</li>\\\n</ol>\\\n<p>设好网络后, 用 route 命令把宿主的默认网关改为虚拟路由器, 在把 DNS 也设置为虚拟路由器的地址. That’s all.</p>\\\n<p>本来想试试 docker , 但是 osx 的 docker 引擎是虚拟机, container 是跑在这个虚拟机里, 貌似比较麻烦或者说不可能实现. 所以用了 virtualbox , 仅提供个思路, 抛砖引玉, 有大神出个 docker 的思路就最吼了!</p>\\\n\\\n<h2>安装</h2><p>根据 <a href=\\\"https://wiki.openwrt.org/doc/howto/virtualbox\\\" target=\\\"_blank\\\">wiki</a> 的说明 , 先把 openwrt 安装到虚拟机里 :</p>\\\n<ul>\\\n<li>下载 <a href=\\\"https://downloads.openwrt.org/chaos_calmer/15.05.1/x86/generic/openwrt-15.05.1-x86-generic-combined-ext4.img.gz\\\" target=\\\"_blank\\\">openwrt-15.05.1-x86</a></li>\\\n<li>解压: <code>gunzip openwrt-15.05.1-x86-generic-combined-ext4.img.gz</code></li>\\\n<li>将解压出来的镜像转化为 virtualbox 的原始格式: <code>VBoxManage convertfromraw --format VDI openwrt-15.05.1-x86-generic-combined-ext4.img openwrt.vdi</code></li>\\\n<li><p>用 virtualbox 建一个虚拟机 openwrt :</p>\\\n<p> Name: openwrt<br/> Type: Linux<br/> Memory size: 512 MB<br/> Use an existing virtual hard disk file: openwrt.vdi</p>\\\n</li>\\\n<li><p>打开 virtualbox 的全局设置,在网络选项卡里新建一个 Host-Only Networks :</p>\\\n<p> IPv4 Address: 192.168.100.2<br/> IPv4 Network Mask: 255.255.255.0<br/> DHCP Server: Disable</p>\\\n</li>\\\n<li><p>打开虚拟机 openwrt 的设置,在网络选项卡里对 「适配器1」进行设置 :</p>\\\n<p> Enable Network Adapter<br/> Attached to: Host-only Adapter<br/> Name: vboxnet0「这里选择在之前步骤新建的 Host- Only Networks 」</p>\\\n<p> 另外再添加一张「适配器2」:</p>\\\n<p> Enable Network Adapter<br/> Attached to: Bridged Adapter<br/> Name: en0: Wi-Fi(AirPort)「这里选择宿主上网的网卡」</p>\\\n</li>\\\n</ul>\\\n<h2>配置虚拟机网络</h2><ul>\\\n<li><p>启动并进入 openwrt , 对网络进行设置 <code>vim /etc/config/network</code> :</p>\\\n<div><table><tbody><tr><td><pre><div>config interface 'loopback'</div><div>    option ifname 'lo'</div><div>    option proto 'static'</div><div>    option ipaddr '127.0.0.1'</div><div>    option netmask '255.0.0.0'</div><div>config interface 'lan'</div><div>    option ifname 'eth0'</div><div>    option type 'bridge'</div><div>    option proto 'static'</div><div>    option ipaddr '192.168.100.1' 「将 lan 地址改为 192.168.100.1 」</div><div>    option netmask '255.255.255.0'</div><div>    option ip6assign '60'</div><div>config interface 'wan'</div><div>    option ifname 'eth1'</div><div>    option proto 'dhcp'</div><div>config interface 'wan6'</div><div>    option ifname 'eth1'</div><div>    option proto 'dhcpv6'</div><div>config globals 'globals'</div><div>    option ula_prefix 'fde9:2442:ec95::/48'</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>在 openwrt 上执行: <code>/etc/init.d/network restart</code> 重启 openwrt 的网络, 在 openwrt 上执行 <code>ifconfig</code> 查看网络,应该可以看到 eth0 的 IP 是我们设定的 192.168.100.1 ,宿主这时可以通过 ssh 登录到 虚拟 openwrt . 而 eth1 网卡已经从上级路由器获取到了对应的 IP 地址, 在 openwrt 上执行 <code>ping <a href=\\\"http://baidu.com/\\\" target=\\\"_blank\\\">baidu.com</a></code> , 不通的话再检查下哪里没做对.</p>\\\n</li>\\\n<li><p>将宿主上执行 :<code>sudo route change default 192.168.100.1</code> 将默认路由设置为 openwrt , 同时在宿主上执行 : <code>sudo networksetup -setdnsservers Wi-Fi 192.168.100.1</code> 将 DNS 设置为 openwrt . 此时所有宿主的流量都被 openwrt 接管, DNS 也在 openwrt 上进行查询. 试着用宿主浏览网页, 网络不通的话再检查下:</p>\\\n<ul>\\\n<li>openwrt 是否已经启动, 并且在 openwrt 里已经可以上网</li>\\\n<li>在宿主上执行 <code>ifconfig vboxnet0</code> 检查 vboxnet0 网卡是否已经准备好, 宿主的数据都是经过这个网卡流向虚拟路由器.</li>\\\n<li>在宿主上执行 <code>netstat -nr | grep default</code> 查看默认路由是否指向了虚拟 openwrt</li>\\\n</ul>\\\n</li>\\\n<li><p>为了方便之后的操作, 在虚拟路由上执行 <code>passwd</code> 更改密码, 然后将宿主的公钥加入 openwrt 的 /etc/dropbear/authorized_keys 中以便免密码登录. 一些常用命令:</p>\\\n<ul>\\\n<li>用 <code>VBoxManage startvm --type headless openwrt</code> , 可以在后台运行 openwrt</li>\\\n<li>需要关闭 openwrt 时, 运行命令: <code>VBoxManage controlvm openwrt poweroff</code></li>\\\n<li><p>在宿主上的 $HOME/.ssh/config 文件内配置 openwrt , 通过 <code>ssh openwrt</code> 登录比起 <code>ssh root@id-address</code> 更方便 : </p>\\\n<div><table><tbody><tr><td><pre><div>Host    openwrt</div><div>    HostName    192.168.100.1</div><div>    User    root</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n</ul>\\\n</li>\\\n</ul>\\\n<h2>透明代理</h2><p>在 openwrt 上设置透明代理的方法有很多 , 个人认为最优雅的组合是 :</p>\\\n<ul>\\\n<li>在 gfvvlist 的基础上 , 自己维护一个需要走代理的域名列表</li>\\\n<li>用 dnsmasq 架设 DNS 服务 , 列表内的域名转发到 shadowsocks 的 ss-tunnel , 让 vps 进行 DNS 查询 , 避免污染 . 域名外的域名直接交给上级路由查询 , 可以获得 cdn 加速 .</li>\\\n<li>dnsmasq 得到列表中域名的 IP 地址后 , 加入一个 ipset 集合中 . 于是我们就得到了一个需要走代理的 IP 地址集合 .</li>\\\n<li>用 iptables 的 ipset 功能 , 目标地址在指定集合内的数据包 , 转发到 shadowsocks 的 ss-redir , 科学上网.</li>\\\n<li>当然 , shadowsocks 的数据全部交给 kcptun 进行加速 .</li>\\\n</ul>\\\n<p>利用以上这个组合 , 就可以根据域名区分数据走向 . 以下仅仅是记录过程 , 了解更多原理请点 : <a href=\\\"https://icymind.com/learn-from-gfw/\\\" target=\\\"_blank\\\">那些从墙上学会的知识</a></p>\\\n<h3>准备相关软件</h3><ul>\\\n<li>下载 <a href=\\\"https://github.com/shadowsocks/openwrt-shadowsocks/releases\\\" target=\\\"_blank\\\">shadowsocks-libev for openwrt</a> 并在宿主上执行 <code>scp shadowsocks-libev*.ipk openrt:~</code> 传送到 openwrt 上 . 在 openwrt 上执行 <code>opkg update &amp;&amp; opkg install shadowsocks-libev_2.5.6-1_x86.ipk</code> 进行安装 .</li>\\\n<li>下载 <a href=\\\"https://github.com/bettermanbao/openwrt-kcptun/releases\\\" target=\\\"_blank\\\">kcptun for linux</a> 并把客户端可执行文件移动到 openwrt 上的系统路径 , 在 openwrt 上执行 : <code>mv client_linux_x386 /usr/bin/kcptun</code></li>\\\n<li>因为只有 dnsmasq-full 才支持 ipset,卸载 dnsmasq 并安装 dnsmasq-full : <code>opkg remove dnsmasq &amp;&amp; opkg install dnsmasq-full</code></li>\\\n<li>安装 ipset : <code>opkg install ipset</code></li>\\\n</ul>\\\n<h3>配置 shadowsocks</h3><ul>\\\n<li><p>/etc/ss-local.json</p>\\\n<div><table><tbody><tr><td><pre><div>{</div><div>    &quot;server&quot;:       &quot;127.0.0.1&quot;,</div><div>    &quot;server_port&quot;:  1070,</div><div>    &quot;local_address&quot;: &quot;0.0.0.0&quot;,</div><div>    &quot;local_port&quot;:   1080,</div><div>    &quot;password&quot;:     &quot;paaasssword&quot;,</div><div>    &quot;timeout&quot;:      300,</div><div>    &quot;method&quot;:       &quot;chacha20&quot;,</div><div>    &quot;fast_open&quot;:    true</div><div>}</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>/etc/ss-tunnel.json</p>\\\n<div><table><tbody><tr><td><pre><div>{</div><div>    &quot;server&quot;: &quot;server-ip&quot;,</div><div>    &quot;server_port&quot;: 8989,</div><div>    &quot;local_address&quot;: &quot;0.0.0.0&quot;,</div><div>    &quot;local_port&quot;: 5353,</div><div>    &quot;password&quot;: &quot;paaasssword&quot;,</div><div>    &quot;timeout&quot;: 300,</div><div>    &quot;method&quot;: &quot;chacha20&quot;,</div><div>    &quot;fast_open&quot;: true</div><div>}</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>/etc/init.d/ss</p>\\\n<div><table><tbody><tr><td><pre><div>#!/bin/sh /etc/rc.common</div><div>START=105</div><div>SERVICE_USE_PID=1</div><div>SERVICE_WRITE_PID=1</div><div>SERVICE_DAEMONIZE=1</div><div>start() {</div><div>    service_start /usr/bin/ss-tunnel -L 8.8.8.8:53 -c /etc/ss-tunnel.json -u</div><div>    service_start /usr/bin/ss-redir  -c /etc/ss-local.json -u</div><div>}</div><div>stop() {</div><div>    service_stop /usr/bin/ss-tunnel</div><div>    service_stop /usr/bin/ss-redir</div><div>}</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>开机启动 : <code>/etc/init.d/ss enable</code> , 手动开启/关闭 : <code>/etc/init.d/ss start|stop</code></p>\\\n</li>\\\n</ul>\\\n<h3>配置kcptun</h3><ul>\\\n<li><p>/etc/kcptun-client.json</p>\\\n<div><table><tbody><tr><td><pre><div>{</div><div>    &quot;remoteaddr&quot;: &quot;server-ip:server-port&quot;,</div><div>    &quot;localaddr&quot;: &quot;:1070&quot;,</div><div>    &quot;mode&quot;:     &quot;fast3&quot;,</div><div>    &quot;crypt&quot;:    &quot;server-crypt&quot;,</div><div>    &quot;nocomp&quot;:    true | false (must be same as server side)</div><div>}</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>/etc/init.d/kcptun</p>\\\n<div><table><tbody><tr><td><pre><div>#!/bin/sh /etc/rc.common</div><div># Copyright (C) 2006-2011 OpenWrt.org</div><div>START=70</div><div>SERVICE_USE_PID=1</div><div>SERVICE_WRITE_PID=1</div><div>SERVICE_DAEMONIZE=1</div><div>start() {</div><div>    service_start /usr/bin/kcptun -c /etc/kcptun-client.json --log /var/log/kcptun.log</div><div>}</div><div>stop() {</div><div>    service_stop /usr/bin/kcptun</div><div>}</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>随开机启动 : <code>/etc/init.d/kcptun enable</code> , 手动启动/停止 : <code>/etc/init.d/kcptun start|stop</code></p>\\\n</li>\\\n</ul>\\\n<h3>配置 iptables</h3><ul>\\\n<li><p>/etc/firewall.user</p>\\\n<div><table><tbody><tr><td><pre><div>#redir packages from openwrt itself</div><div>iptables -t nat -A OUTPUT -p tcp -m set --match-set SS dst -j REDIRECT --to-port 1080</div><div>iptables -t nat -A OUTPUT -p udp -m set --match-set SS dst -j REDIRECT --to-port 1080</div><div># redir packages from client</div><div>iptables -t nat -A PREROUTING -p tcp -m set --match-set SS dst -j REDIRECT --to-port 1080</div><div>iptables -t nat -A PREROUTING -p udp -m set --match-set SS dst -j REDIRECT --to-port 1080</div><div># new ipset: SS</div><div>ipset -N SS hash:ip</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>使 iptables 规则生效 : <code>/etc/init.d/firewall restart</code></p>\\\n</li>\\\n</ul>\\\n<h3>配置 dnsmasq</h3><ul>\\\n<li><p>/etc/dnsmasq.conf</p>\\\n<div><table><tbody><tr><td><pre><div>conf-dir=/etc/dnsmasq.d/</div><div>min-cache-ttl=3600</div><div>cache-size=9999</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>/etc/dnsmasq.d/over-gfw.conf , 可以用这个 <a href=\\\"https://github.com/icymind/domains-to-dnsmasq\\\" target=\\\"_blank\\\">domains-to-dnsmasq 脚本</a> 自动生成 :</p>\\\n<div><table><tbody><tr><td><pre><div>server=/google.com/127.0.0.1#5353</div><div>ipset=/google.com/SS</div><div>server=/twitter/127.0.0.1#5353</div><div>ipset=/twitter/SS</div><div>...</div><div>...</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>重启 dnsmasq , 使配置文件生效 : <code>/etc/init.d/dnsmasq restart</code></p>\\\n</li>\\\n</ul>\\\n<p>全部配置后之后就可以上资本主义网站了 . 但是当宿主的外部网络发生变化 , 比如连接另一个 Wi-Fi 时 , 我们自定义的 iptables 规则会被系统重写而丢失 , kcptun 在没有网络的情况下也会崩溃退出 , 因此可以加一个脚本监控这些状态 , 随时恢复到可以正常使用的状态:</p>\\\n<ul>\\\n<li><p>/root/keep-kt-ss-alive</p>\\\n<div><table><tbody><tr><td><pre><div>#!/bin/sh</div><div>kcptun_pid=$(pgrep kcptun)</div><div>ss_redir_pid=$(pgrep ss-redir)</div><div>ss_tunnel_pid=$(pgrep ss-tunnel)</div><div>iptable_rules=$(iptables -S -t nat | grep 1080)</div><div># KCPTUN</div><div>if [ -z &quot;$kcptun_pid&quot; ];then</div><div>    /etc/init.d/kcptun restart</div><div>fi</div><div># SHADOWSOCKS</div><div>if [ -z &quot;$ss_redir_pid&quot; ] || [ -z &quot;$ss_tunnel_pid&quot; ];then</div><div>    /etc/init.d/ss restart</div><div>fi</div><div># IPTABLES</div><div>if [ -z &quot;$iptable_rules&quot; ];then</div><div>    /etc/init.d/firewall restart</div><div>fi</div></pre></td></tr></tbody></table></div>\\\n<p> 别忘了给脚本添加可执行权限 : <code>chmod +x /root/keep-kt-ss-alive</code></p>\\\n</li>\\\n<li><p>新建计划任务 , 每分钟执行 keep-kt-ss-alive 脚本 : <code>crontab -e</code> </p>\\\n<div><table><tbody><tr><td><pre><div>* * * * * /root/keep-kt-ss-alive</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>还需要让系统的 cron 服务随开机启动 , 我们的计划任务才能执行: <code>/etc/init.d/cron enable &amp;&amp; /etc/init.d/cron start</code></p>\\\n</li>\\\n</ul>\\\n<h2>自动化</h2><h3>随宿主开机启动 openwrt</h3><ul>\\\n<li><p><code>cat ~/Library/LaunchAgents/com.icymind.openwrt.sh</code></p>\\\n<div><table><tbody><tr><td><pre><div>#!/bin/bash</div><div># iCyMind &lt;icyminnd@gmail.com&gt;</div><div>function stopvm()</div><div>{</div><div>    if [ -n &quot;$(/usr/local/bin/VBoxManage list runningvms | grep openwrt)&quot; ];then</div><div>        echo &quot;$(/bin/date): shutdown openwrt&quot;</div><div>        /usr/local/bin/VBoxManage controlvm openwrt poweroff</div><div>    fi</div><div>    exit 0</div><div>}</div><div>function startvm()</div><div>{</div><div>    if [ -z &quot;$(/usr/local/bin/VBoxManage list runningvms | grep openwrt)&quot; ];then</div><div>        echo &quot;$(/bin/date): startup openwrt&quot;</div><div>        /usr/local/bin/VBoxHeadless -s openwrt &amp;</div><div>        wait $!</div><div>    fi</div><div>}</div><div>trap stopvm HUP KILL TERM</div><div>startvm;</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p><code>cat ~/Library/LaunchAgents/com.icymind.openwrt.plist</code></p>\\\n<div><table><tbody><tr><td><pre><div>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</div><div>&lt;!DOCTYPE plist PUBLIC &quot;-//Apple Computer//DTD PLIST 1.0//EN&quot; &quot;<a href=\\\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\\" target=\\\"_blank\\\">http://www.apple.com/DTDs/PropertyList-1.0.dtd</a>&quot;&gt;</div><div>&lt;plist version=&quot;1.0&quot;&gt;</div><div>  &lt;dict&gt;</div><div>    &lt;key&gt;Label&lt;/key&gt;</div><div>    &lt;string&gt;com.icymind.openwrt&lt;/string&gt;</div><div>    &lt;key&gt;ProgramArguments&lt;/key&gt;</div><div>    &lt;array&gt;</div><div>        &lt;string&gt;/Users/simon/Dropbox/Script/com.icymind.vboxopenwrt.sh&lt;/string&gt;</div><div>    &lt;/array&gt;</div><div>    &lt;key&gt;KeepAlive&lt;/key&gt;</div><div>    &lt;true/&gt;</div><div>    &lt;key&gt;RunAtLoad&lt;/key&gt;</div><div>    &lt;true/&gt;</div><div>    &lt;key&gt;UserName&lt;/key&gt;</div><div>    &lt;string&gt;simon&lt;/string&gt;</div><div>    &lt;key&gt;WorkingDirectory&lt;/key&gt;</div><div>    &lt;string&gt;/Users/simon/&lt;/string&gt;</div><div>  &lt;/dict&gt;</div><div>&lt;/plist&gt;</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p>加载 launchd 任务 : <code>launchctl bootstrap gui/501 ~/Library/LaunchAgents/com.icymind.openwrt.plist</code> . 其中 501 是用户的 uid , 可以通过执行 <code>id -u</code> 获知 .</p>\\\n</li>\\\n</ul>\\\n<h3>宿主开机时/网络变化时 , 自动更改网关和 DNS</h3><ul>\\\n<li><p><code>cat ~/Dropbox/Script/com.icymind.network.sh</code></p>\\\n<p> 这个脚本会在 vboxnet0 网卡激活后 , 将宿主的默认网关/ DNS 指向虚拟机 . 同时重启 openwrt 的网络 , 让它重新从上游路由器获取 IP 地址.</p>\\\n<div><table><tbody><tr><td><pre><div>#!/bin/bash</div><div># make sure your had set nopasswd for route/networksetup command.</div><div>INTERFACE=&quot;Wi-Fi&quot;</div><div>GATEWAY=&quot;192.168.100.1&quot;</div><div>USER=&quot;root&quot;</div><div># wait for vboxnet0 available</div><div># vboxnet0 active after virtual machine startup. If change route table before vboxnet0 active, your network will be unreachable</div><div>while true; do</div><div>    ifconfig vboxnet0</div><div>    if [ $? -eq 0 ]; then</div><div>        break</div><div>    fi</div><div>    sleep 5</div><div>done</div><div># restart openwrt network to renew ip from upper dhcp</div><div>ssh $USER@$GATEWAY &quot;/etc/init.d/network restart &amp;&amp; sleep 4 &amp;&amp; /etc/init.d/kcptun restart &amp;&amp; /etc/init.d/firewall restart &gt; /dev/null 2&gt;&amp;1&quot;</div><div># change default route.</div><div>sudo route change default $GATEWAY</div><div>sudo networksetup -setdnsservers $INTERFACE $GATEWAY</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n<li><p><code>cat ~/Library/LaunchAgents/com.icymind.network.plist</code></p>\\\n<p> 在 OSX 上 , 每次开机或者网络环境发生变化时:</p>\\\n<ul>\\\n<li><code>/etc/resolv.conf</code></li>\\\n<li><code>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</code></li>\\\n<li><p><code>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</code> </p>\\\n<p>这三个文件都会发生变化 , 写个 Agent 监控这几个文件 , 当发生改变时自动执行更改网关的脚本.</p>\\\n<div><table><tbody><tr><td><pre><div>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</div><div>&lt;!DOCTYPE plist PUBLIC &quot;-//Apple Computer//DTD PLIST 1.0//EN&quot; &quot;<a href=\\\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\\" target=\\\"_blank\\\">http://www.apple.com/DTDs/PropertyList-1.0.dtd</a>&quot;&gt;</div><div>&lt;plist version=&quot;1.0&quot;&gt;</div><div>  &lt;dict&gt;</div><div>    &lt;key&gt;Label&lt;/key&gt;</div><div>    &lt;string&gt;com.icymind.network&lt;/string&gt;</div><div>    &lt;key&gt;ProgramArguments&lt;/key&gt;</div><div>    &lt;array&gt;</div><div>        &lt;string&gt;/Users/simon/Dropbox/Script/com.icymind.network.sh&lt;/string&gt;</div><div>    &lt;/array&gt;</div><div>    &lt;key&gt;WatchPaths&lt;/key&gt;</div><div>    &lt;array&gt;</div><div>        &lt;string&gt;/etc/resolv.conf&lt;/string&gt;</div><div>        &lt;string&gt;/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist&lt;/string&gt;</div><div>        &lt;string&gt;/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist&lt;/string&gt;</div><div>    &lt;/array&gt;</div><div>    &lt;key&gt;RunAtLoad&lt;/key&gt;</div><div>    &lt;true/&gt;</div><div>  &lt;/dict&gt;</div><div>&lt;/plist&gt;</div></pre></td></tr></tbody></table></div>\\\n</li>\\\n</ul>\\\n</li>\\\n<li><p>同理用 <code>launchctl bootstrap gui/501 ~/Library/LaunchAgents/com.icymind.network.plist</code> 加载并执行 .</p>\\\n</li>\\\n</ul>\\\n<h2>log –verbose</h2><ul>\\\n<li>开始用的是 64 位的 openwrt 镜像 , 装了两遍虚拟路由都不能从上级路由器获取到 IP , 于是改用 32 位的镜像.</li>\\\n<li><p>更改网关和 DNS 需要 <code>sudo route</code> 和 <code>sudo networksetup</code> , 为了能让脚本顺利执行 , 需要在 /etc/sudoers 中添加:</p>\\\n<div><table><tbody><tr><td><pre><div>simon   ALL=(ALL) NOPASSWD: /usr/sbin/networksetup, /sbin/route</div></pre></td></tr></tbody></table></div>\\\n<p> 其中 simon 是我的用户名</p>\\\n</li>\\\n<li><p>重启 openwrt 的网络需要登录到路由器执行 , 为了让脚本能顺利执行 , 需要开启密钥登录:</p>\\\n<ul>\\\n<li>如果宿主没有密钥对的话 , 用 <code>ssh-keygen</code> 生成 , 公钥在宿主的 ~/.ssh/id_rsa.pub</li>\\\n<li>将宿主公钥的内容复制到 openwrt 的 /etc/dropbear/authorized_keys 文件内即可</li>\\\n</ul>\\\n</li>\\\n</ul>\\\n</div></div></div><br/></div></span>\\\n</div></body></html>\\u0000\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":18744}]"
metadata_diff: {"new":{"id":"8d03c71bba754985ab02876771a7ef98","parent_id":"f67288c3a0be4374b5d532b5dcc3aabc","latitude":"0.00000000","longitude":"0.00000000","altitude":"0.0000","author":"","source_url":"","is_todo":0,"todo_due":0,"todo_completed":0,"source":"joplin-desktop","source_application":"net.cozic.joplin-desktop","application_data":"","order":1764348875471,"user_updated_time":1764345570761,"markup_language":2,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","user_data":"","deleted_time":1764365029762},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2025-11-28T21:24:57.719Z
created_time: 2025-11-28T21:24:57.719Z
type_: 13