树莓派网关代理

参考文章树莓派二代 dnsmasq ipset iptables shadowsocks 网关代理将gfwlist转换成带ipset的dnsmasq规则,适用于OpenWrt智能上网使用ipset让openwrt上的shadowsocks更智能的重定向流量的补充终于折腾好了。

先简单说下原理。一般来说,正常的上网是通过路由器拨号上网并充当网关进行 NAT 转发,实现本地局域网内多台设备同时上网。而问题在于,路由器一般功能有限无法提供更加智能的网关业务处理。除非路由器支持第三方固件升级,如 OpenWrt 或 DDWrt 等。实际上,除开路由器网关,可以使用其他电脑(比如树莓派)充当二级网关,来解决此问题。

原有的网络拓扑是路由器 IP 为 192.168.1.1,通过路由器上的 DHCP 指定网关为 192.168.1.1,主 DNS 服务器为 119.29.29.29 备选 DNS 服务器为 114.114.114.114。

修改后的网络拓扑是路由器 IP 为 192.168.1.1,树莓派 IP 为 192.168.1.2,通过路由器上的 DHCP 指定网关为 192.168.1.2,主 DNS 服务器为 192.168.1.2 备选 DNS 服务器为 119.29.29.29。树莓派的网关为 192.168.1.1,手工指定主 DNS 服务器为 119.29.29.29 备选 DNS 服务器为 114.114.114.114。

所以第一步需要将树莓派设置为 iface eth0 inet static,执行 sudo nano /etc/network/interfaces,修改内容如下:

auto lo

iface lo inet loopback

auto eth0
#iface eth0 inet dhcp
iface eth0 inet static
        address 192.168.1.2
        netmask 255.255.255.0
        network 192.168.1.0
        gateway 192.168.1.1

然后,执行 sudo nano /etc/resolv.conf,修改内容如下:

nameserver 119.29.29.29
nameserver 114.114.114.114

下一步是打开 NAT 网关,执行 sudo nano /etc/sysctl.conf,修改指定行为:

net.ipv4.ip_forward=1

检查 sudo nano /etc/iptables.up.rules,如果有 8080 转发,请禁止

:POSTROUTING ACCEPT [0:0]
#-A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8081
#-A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
COMMIT

NAT 需要重启才能生效。这样,树莓派可以充当一个普通的网关代理,但没有 DNS 服务。此时可以将客户端网关修改为 192.168.1.2,DNS 服务器指定为 119.29.29.29 检查是否可以上网。

我们知道,通过域名访问任何一项网络服务,都先必须解析域名。现在要做的就是,树莓派使用 dnsmasq 提供局域网的 DNS 服务,使用特殊的规则解析指定的域名,并将解析到的 IP 加入 ipset 规则组,然后 iptables nat 使用 ipset 指定的规则组自动走 shadowsocks 的代理线路进行访问。从而达到我们的目的。

需要安装的包有:sudo apt-get install ipset dnsmasq shadowsocks-libev

我们并不需要 shadowsocks-libev 自带的 server 服务,执行 sudo update-rc.d shadowsocks-libev remove 禁止自动启动服务。

替代的是使用 ss-redir 连接 shadowsocks 代理服务器(通常会使用的是 ss-local 来开启 socks 代理,但 redir 会减少 socks 代理开销)。

手工建立 shadowsocks-redir 服务,执行:

sudo cp /etc/init.d/shadowsocks-libev /etc/init.d/shadowsocks-redir
sudo cp /etc/default/shadowsocks-libev /etc/default/shadowsocks-redir
sudo cp /etc/shadowsocks-libev/config.json.dpkg-old /etc/shadowsocks-libev/redir.json

需要 sudo nano /etc/init.d/shadowsocks-redir 将相关 shadowsocks-libev 改为 shadowsocks-redir,以及 ss-server 改为 ss-redir

# Provides:          shadowsocks-redir
DESC=shadowsocks-redir       # Introduce a short description here
NAME=shadowsocks-redir       # Introduce the short server's name here
DAEMON=/usr/bin/ss-redir     # Introduce the server's location here

sudo nano /etc/default/shadowsocks-redir 修改 CONFFILE

CONFFILE="/etc/shadowsocks-libev/redir.json"

sudo nano /etc/shadowsocks-libev/redir.json 配置 local_address 和端口,需要绑定 0.0.0.0 和 1080 端口(建议)

{
    "server":"example.com",
    "server_port":10307,
    "local_address":"0.0.0.0",
    "local_port":1080,
    "password":"password"
}

开启服务,并设置自动启动服务

sudo service shadowsocks-redir start 
sudo update-rc.d shadowsocks-redir defaults

可以使用 sudo netstat -nlp | grep redir 查看服务端口是否正常。

使用 sudo ipset -N ss iphash 创建新的 ipset 规则组,因为系统重启后 ipset 数据会丢失,建议将 ipset -N ss iphash 加入到 /etc/init.d/networkingstart> 中,如

case "$1" in
start)
        if init_is_upstart; then
                exit 1
        fi
        ipset -N ss iphash
        process_options
        check_ifstate

否则,修改 iptables 默认规则后,会导致 ss 规则找不到,从而无法启动网络。

修改 iptables nat 规则,sudo iptables -t nat -A PREROUTING -p tcp -m set --match-set ss dst -j REDIRECT --to-port 1080

因为 iptables 重启后规则失效,需要修改 sudo nano /etc/iptables.up.rules

:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m set --match-set ss dst -j REDIRECT --to-port 1080
COMMIT

下一步就是配置 dnsmasq,首先打开 sudo nano /etc/dnsmasq.conf,修改

# Include another lot of configuration options.
#conf-file=/etc/dnsmasq.more.conf
conf-dir=/etc/dnsmasq.d

然后创建一个 google 的规则 sudo nano /etc/dnsmasq.d/google.conf 内容为

server=/.googleapis.com/208.67.222.222#5353
ipset=/.googleapis.com/ss
server=/.google.com/208.67.222.222#5353
ipset=/.google.com/ss

使用 sudo service dnsmasq restart 重启服务,并将客户端的网关和 DNS 服务器都改为 192.168.1.2 即可以直接访问 google。

最后一步就是每天自动更新 gfwlist 规则为 dnsmasq 配置了。执行 sudo nano /etc/cron.daily/dnsmasq-gfwlist.py,内容为 https://gist.github.com/larryli/bf0671b41ede5d77c52862f57fff6159

所有测试没问题后,请将路由器 DHCP 服务器,将网关设置为 192.168.1.2,DNS 服务器为 192.168.1.2 即完成所有配置。

树莓派+USB 摄像头家用监控

raspbian 下很简单,直接安装 motion 即可:

sudo apt-get install motion

不过需要手工打开服务配置:

sudo nano /etc/default/motion

start_motion_daemon=no 修改为:

start_motion_daemon=yes

处理一个小的权限问题:

sudo chmod 777 /var/lib/motion

sudo service motion start 启动服务。

默认会使用 /dev/video0 这个设备,请确定 USB 摄像头插上去,能否 lsusb 列出,并且设备映射成功。

在路由器开放外网端口之前可以修改 /etc/motion/motion.conf 文件中以下配置:

width 640
height 480 # 视频大小
text_right Larry Li(Shenzhen)n%Y-%m-%d %T-%q # 右下角文字
text_left CAMERA rpi1 # 左下角文字
target_dir /var/lib/motion # 文件存放位置,需要 chmod 777
picture_filename %Y%m%d/%H%M%S-%v-%q # 也可以按 %Y/%m/%d/%H%M%S-%v-%q 年月日一层一层建目录存放
movie_filename %Y%m%d/%H%M%S-%v # 其他几个 filename 配置也相同处理
stream_port 8081 # 指定实时 http 监控端口
stream_localhost off # 需要将 on 修改为 off 取消仅 localhost 访问限制
stream_limit 2 # 最好设置一个访问数限制
stream_auth_method 1 # 1 是标准的 basic auth
stream_authentication username:password # 用户名和密码
webcontrol_port 0 # 关闭控制端口,或者也设置 basic auth 的用户名和密码 

然后使用 btsync 把 /var/lib/motion 共享给手机和远程电脑,我直接使用了 rw 读写模式,手工在远程删除旧文件。

PHP 切换到 7.0

用的是 ppa:ondrej/php-7.0

sudo add-apt-repository ppa:ondrej/php-7.0
sudo apt-get update
udo apt-get install php7.0-cli php7.0-fpm php7.0-gd php7.0-json php7.0-mcrypt php7.0-mysql php7.0-readline php7.0-sqlite php-apcu

有一个坑需要注意的是,sock 文件是从 /var/run/php5-fpm.sock 变成了 /var/run/php/php7.0-fpm.sock

因为 VPS 性能所限,整体提升并不是很给力,只是一两倍而已。

Git 提交 GnuPG 自动签名

一般来说使用 git commit -S 就调用 gpg 工具自动搜索 user.name<user.email> 对应的私钥来签名提交。

git 2.0 以上版本提供了 commit.gpgsign 设置可以自动打开 gpg 签名选项。

然后配合 user.signingkey 就可以设置默认的 key 来自动签名了。

git config --global user.name "Larry Li"
git config --global user.email larryli@qq.com
git config --global user.signingkey 2D8B022C
git config --global commit.gpgsign true

密钥 2D8B022C 可以通过 gpg -K 查看可用的私钥。

WebSocket、API 与 Push 推送

WebSocket 从 2010 年出现到现在已经五六年了,目前来说主流浏览器已经对其普遍支持,但实际运行却非常之少。

一般来说,WebSocket 都是双向全双工通信的。所以很容易设计一个异步协议 WAMP,提供异步的 RPC 远程调用Publish & Subscribe 模式实现。

但是,这种设计完全无视了 WebSocket 是基于 HTTP 协议的。也就是说,HTTP 使用 url 来路由,WebSocket 也同样可以用 url 来路由。

就拿 Pub/Sub 模式来说,WebSocket 天生就可以使用不用的路由来表示不同的 Pub。

而浏览器作为 Client 去 Call 服务器不正是 RESTful API 该做的事情么?

那么,除非是服务器要去 Call 浏览器端,WAMP 的大部分设计都是不需要的。

WebSocket 真的只需要简单的使用,就如它一开始被赋予的使命一样,作为一个 Push 及时的把服务端最新的消息推送到客户端。甚至消息都不需要包含实体,而只是一个通知即可。

SSL 证书更新

一晃使用 StartSSL 免费证书已经好几年了。证书有效期只有一年,每年得提前两个星期来申请新证书更换旧的。

而且很坑的是,至今没有弄懂如何使用已有的私钥来申请新的证书。每次都是完整更新一次才罢。

据说这个月 Let’s Encrypt 就会开始提供全新的免费 SSL 证书方案。但目前为止除了月更的博客少的可怜几行文字外,都没什么可见的效果。

不过,这几年使用 SSL 的感受,其实加密的性能真的不是问题了。当然,对于 C10K 那种访问量来说,CPU 和内存开销当然不会少。

而且除开免费的 SSL 证书,一些收费证书的价格也不是那么高高在上的,

除开这些,SSL 真的很不错。