Spring Boot连接MongoDB

最近在做的项目用到了Mongo DB,发现在开启用户认证的情况下,用URI的方式连接总是提示认证失败,只有在分别设置了username ,password , database等字段才能连接成功。

1
2
3
4
5
6
7
spring:
data:
mongodb:
authentication-database: ${MONGODB_AUTHENTICATION_DATABASE:admin}
username: ${MONGODB_USERNAME:username}
password: ${MONGODB_PASSWORD:password}
database: ${MONGODB_DATABASE:database}

之前一直认为Spring Boot连接Mongo DB的方式和连JDBC差不多,今天抽空研究了下,发现URI中的数据库名其实是存储用户认证信息的数据库,实际数据库要通过database设定:

1
2
3
4
5
spring:
data:
mongodb:
database: ${MONGODB_DATABASE:database}
uri: ${MONGODB_URI:mongodb://username:password@localhost:27017/authentication_database}

官方文档

/database

Optional. The name of the database to authenticate if the connection string includes authentication credentials in the form of username:password@. If /database is not specified and the connection string includes credentials, the driver will authenticate to the admin database. See also authSource.

AWS S3 'Permissions on the destination queue do not allow S3 to publish notifications from this bucket' 问题的解决方法

在AWS平台给S3配置发送存储事件到SQS时遇到了如下错误提示:

Unable to validate the following destination configurations. Permissions on the destination queue do not allow S3 to publish notifications from this bucket.

在IAM那里捣鼓了半天,给S3加上了SQS相关的权限后依然提示错误信息。 正当毫无头绪的时发现SQS有个Permission标签,在这里配置相关权限后就可以解决错误提示了。

Image

原来SQS默认是不接受发送过来的事件的,印象当中之前是不需要配置的,也不知道这功能是啥时候加上去的,感觉AWS的权限系统有时太复杂了。。。

Openwrt x86安装教程

网上Openwrt x86虚拟机安装的教程一大堆,却很少见到非虚拟机的教程,现在正好有机会重新刷机,就顺便把步骤记录一下,免得再次踩坑。

镜像下载

第一步就是下载openwrt x86的镜像,这里两个镜像可以选择,带squashfs的刷机后会有一个只读的分区,带ext4的所有分区都是可读写的。本教程是以combined-ex4为例子的。

下载地址:openwrt-18.06.2-x86-64-combined-ext4.img.gz

combined-squashfs 和 combined-ex4 的区别:

combined-squashfs.img.gz This disk image uses the traditional OpenWrt layout, a squashfs read-only root filesystem and a read-write partition where settings and packages you install are stored. Due to how this image is assembled, you will have only 230-ish MB of space to store additional packages and configuration, and Extroot does not work.

combined-ext4.img.gz This disk image uses a single read-write ext4 partition with no read-only squashfs root filesystem, which allows to enlarge the partition. Features like Failsafe Mode or Factory Reset won’t be available as they need a read-only squashfs partition to function.

制作linux启动盘

我们需要两个U盘,其中一个就是用来做linux启动盘,这里以SystemRescueCd为例,制作USB启动盘的教程可一参考这里:Installing-SystemRescueCd-on-a-USB-stick/

USB启动盘制作好后,将下载下来的openwrt安装包拷贝到另一个U盘。

安装镜像

将两个U盘插入软路由,以linux启动盘启动,成功进入系统后执行以下命令将第二个U盘挂载到系统里:

1
2
mkdir /mnt/usb
mount /dev/sdx /mnt/usb

解压并将镜像刷到软路由内存里:

1
2
3
cd /mnt/usb
gunzip openwrt-18.06.2-x86-64-combined-ext4.img.gz
dd if=openwrt-18.06.2-x86-64-combined-ext4.img of=/dev/sdX

其中sdx就是你软路由的安装盘。

PS:官网里的步骤并没有提到解压这一步骤,实际操作中直接dd的话,openwrt是无法启动的,可能是linux系统的差异。

分区扩容(可选)

刷入openwrt后,执行fdisk -l,就会看到软路由的sdx盘被分成了两个分区,你会发现第二个分区只有256M,这里就可以调节第二个分区的大小,将硬盘的剩余容量全部划分到第二个分区:

  1. fdisk -l /dev/sdx将第二个分区的起始扇区号start的值记下来
  2. fdisk /dev/sdx 进入修改硬盘分区信息
  3. 输入d,然后回车
  4. 这里会提示你要删除哪个分区,输入2,然后回车
  5. 输入n,然后回车,选择分区类型primaryextended都可以。
  6. 选择分区后会让你输入分区开始扇区号,这里输入之前记下来的扇区号
  7. 输入w,这时候会提示你Partition #2 contains a ext4 signature. Do you want to remove the signature?这一步很重要,这里要选no
  8. 输入w,然后回车
  9. 分区完成后执行resize2fs /dev/sdx2,分区扩容就大功告成了。

系统配置

  • 重启进入Openwrt系统后,系统会开放一个lan口,将网线接入这个lan口后就可以通过192.168.1.1来访问路由器管理界面了。
  • 进入管理界面后需要设置管理员密码,同时你可以上传ssh key,免得每次ssh都需要输入密码。
  • interfaces页面,LAN标签页面,在Physical settings->Interface你可以修改路由的lan口,将另外几个没开放的lan口都勾选。
  • WAN标签页面,Protocol选择PPPoE,输入宽带密码,save and apply就可以上网了。

应用安装

我们会安装一些应用,但这里有个坑就是应用的安装源是http的,可能会被劫持,所以要修改成https的。先执行以下命令,安装必备的包:

1
2
3
4
opkg update
opkg install ca-certificates ca-bundle
opkg install libustream-mbedtls
opkg install git-http curl

修改源为https

1
2
3
4
5
//将http改为https
vim /etc/opkg/distfeeds.conf
opkg update
//安装一些调试用的软件
opkg install bind-dig

一些常见问题

  1. Samba添加用户与设置密码

    1
    2
    vi /etc/passwd
    smbpasswd -a samba
  2. dnsmasqdnsmasq-full的区别

    dnsmasq-full多了ipset功能

  3. dnsmqsq --no-resolv

    1
    2
    --no-resolv
    Don't read /etc/resolv.conf. Get upstream servers only from the command line or the dnsmasq configuration file.
  4. ss-tunnel dns解析不了

    一般原因有以下几点:

    1. ss-tunnel 未加上-u参数,开启udn relay

    2. ss-server 未加上-u参数,开启udn relay

    3. 服务端未开启端口

    调试用的命令:

    1
    2
    3
    4
    5
    6
    7
    //dnstracer
    dnstracer -vo -s 127.0.0.1 google.com

    //dns测试
    dig +trace google.com
    // dns请求也可以直接发送给ss-tunnel
    dig google.com @127.0.0.1 -p 5353
  5. 开启ss-rules后域名无法解析

    具体什么原因不是很清楚,可能是iptablesudp转发有点问题,ss-redir for UDP这项打勾去掉即可。

一些定时任务脚本

写了一些定时任务脚本,这里记录一下。

参考

hexo-deploy-git提交历史丢失的解决方法

迫于笔记本太重再加上每天上下班要背两小时多,笔记本就一直丢在公司里了。家里的windows越用越不爽,装了ubuntu折腾了一阵子发现不是太好用,V站好多推荐manjaro linux,用下来很顺手而且非常稳定,以后家中主力操作系统就用manjaro了。

由于之前一直是在笔记本上写博客的,最近在manjaro上写博客提交后发现github pages的提交历史全丢了,一查下来是hexo-deployer-git这个插件搞的鬼,该插件第一次提交时会force push,覆盖仓库代码,插件作者似乎无意修复这个BUG,遂想弃用这插件。

网上查下来发现用travis ci来部署github pages是个不错的解决方法,而且这样的话不用每次都手动生成page和提交了。

实现方法也很简单,在项目里加上.travis.yml文件:

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
language: node_js

node_js:
- 11.10.0

cache: npm

script:
- ./node_modules/hexo/bin/hexo generate

deploy:
provider: pages
skip-cleanup: true
keep-history: true
github-token: $GITHUB_TOKEN
local-dir: public
repo: wancaibida/blog
target-branch: master
on:
branch: master

notifications:
email:
recipients:
- wancaibida@gmail.com
on_success: always

设置下github pages的仓库名称,在github上创建一个权限为public_repo 的token给travis用就好了。

记wr1200js刷机遇到的问题

前几天入手了一台wr1200js路由器,到手后成功刷上了openwrt。但重启后发现路由器的配置都丢失了,连管理密码都丢了,网上好多人刷了openwrt后也遇到这样的问题,有说法是路由器闪存读写次数过多坏了,但这刚买的因该不会是这问题,后来在重新刷了下sysupgrade.bin就没这问题了,可能是openwrt在某些条件下会触发这问题。

路由器相关的一些研究

家中房间里的5G信号不好,每次都得手动切换到2.4G信号,有点麻烦,所以想在房间里弄一台AP,来实现无线无缝漫游,期间做了不少研究,故在此记录一下。

路由器/AP

网上看了一圈AP的价格都不便宜,可能是家用AP需求少且大部分是商用的原因,关键还要上POE。论坛好多推荐ubnt的,看了下普通版都要700+rmb。

千兆路由器好一点的基本是200左右的价格,但这个价位的厂家路由系统比较挫,还不能刷机。在再加点钱都赶上京东618 ac66u b1 499的价格了。

那有没有又便宜要好的路由呢,V站好多人都推荐这几款:

  • 斐讯K2P
  • 联想Newifi系列
  • 友华wr1200js

斐讯K2P

这个路由器现在都涨到120+了,如果要买的话要买a1版本的。

优点是做工好,有千兆网口,信号貌似是最好的。

缺点是现在比较难买,刷机的话要先上恩山论坛网友开发的breed, breed 就是路由器上的bootloader,breed一开始是基于u-boot的,现在好像是作者自主开发的,但这东西不开源,存在安全风险。固件可以刷padavan,padavan最初是由这个固件https://bitbucket.org/padavan/rt-n56u修改过来的,比较有名的是荒野无灯的,但这个也没开源。github上也有基于padavan开源的,不放心的可以拿来自己编译。

联想Newifi

联想这边就看了newifi3,这款路由器配置比k2p还要好,价格比k2p还要便宜,某宝的价格才80+,但这款的bootloader被官方锁了,如果要刷第三方固件的话要先越狱,恩山有越狱文件。刷机也是breed+恩山上一大堆网友上传的固件,风险自负,还有一个缺点就是这款信号比较差。

友华wr1200js

友华wr1200js配置和k2p差不多,但做工、信号没有k2p好,最终选择了这款,某宝138入手。这款路由器最大的优点是bootloader没有锁,可以直接上传第三方固件!!还有一个是openwrt完美支持,固件下载地址

Openwrt 和 NAT

喜欢路由器刷机的都知道openwrt,路由器刷了openwrt基本上就告别了硬件nat(貌似MT7621是支持的),由路由器CPU来实现nat,由于路由器CPU的性能都比较弱如果再加上一些附带的功能,路由器CPU就有点力不从心了,这是就推荐openwrt x86了。

MESH网络

研究了下mesh网络,研究下来一些mesh设备是通过在开一个无线频道来实现组网的,貌似无线组网的效果都不怎么好,要走有线回程才靠谱。

一些实现方案:

无线漫游

比较省钱的无线漫游方式就是路由器设置成AP模式,要相同SSID,要隔开几个频道。

专业的AP都带管理功能的。

参考

MT7621 路由性能评测

300m,600m还是1200m——读懂无线路由器的速度标称

如何选购无线路由器?有几个坑一定要避免

路由器透明代理

作为程序员的都知道,现在比较流行的科学上网方式是$$。$$搭建步骤简单,速度快,相比其他的科学上网方式比较轻量。但这种方式也有一些缺点,比如需要在本机安装客户端,维护服务端信息等缺点,路由器透明代理就是为了解决这些问题而诞生的 。

传统科学上网实现方式

传统的科学上网方式是在本机安装$$客户端,不同平台的客户端如下:

  • IOS
    • ShadowRocket(国区已下架)
    • Surge(国区已下架)
  • Mac OS
    • Shadowsocks NG
    • Surge
    • ss-local
  • Linux
    • ss-local
  • Windows
    • Shadowsocks

代理模式

$$一般有两种代理模式,

  1. 自动切换模式

    • 黑名单模式,只代理被墙的网站,对于名单中匹配的网站进行代理,如果不匹配则直接连接,比较著名的 有GFW List
    • 白名单模式,默认代理,对于名单中匹配的网站进行直连。白名单模式在不同平台上的效果不同,在IOS可以实现白名单模式,在Mac OS 上只支持黑名单模式,如果要实现需要做一些hack操作,如:ShadowsocksX-NG实现白名单模式
  2. 全局模式

    所有流量都走代理,这个在不同平台上表现也不同,在Mac os上只能代理部分流量,像CLI的流量需要额外配置。

传统代理模式的缺点

传统的代理模式的缺点也很明显:

  1. 需要安装客户端,且需要在所有客户端配置服务器信息
  2. 无法代理系统级流量或需要额外设置
  3. 无法实现大陆白名单模式(除了大陆以外的网站都走代理)
  4. 被屏蔽的网站越来越多,所有客户端都需要更新名单

路由器透明代理

路由器透明代理,说直白点就是在路由器实现科学上网功能。路由器透明代理的优点很明显,无需在本机安装客户端,只需在路由器维护服务器信息及黑白名单,且能代理系统级流量。

数据流逻辑图

如下图所示, 路由器透明代理主要是两个流程,DNS解析流程与流量代理流程。
数据逻辑图

实现原理

路由器透明代理主要依赖如下工具:

  1. iptables
  2. ipset
  3. ss-redir
  4. ss-tunnel
  5. dnsmasq

dnsmasq+ss-tunnel

dnsmasqss-tunnel主要是用来解决域名污染的问题,dnsmasq会将国外域名dns解析请求通过ss-tunnel转发到shadowsocks服务器

dnsmasq配置文件:

https://cokebar.github.io/gfwlist2dnsmasq/dnsmasq_gfwlist.conf

1
2
3
4
5
server=/google.com/127.0.0.1#5353
server=/google.co.ma/127.0.0.1#5353
server=/google.com.af/127.0.0.1#5353
server=/google.com.ag/127.0.0.1#5353
server=/google.com.ai/127.0.0.1#5353

如上面的代码所示,遇到如需要解析google.com的域名时,dnsmasq会将解析请求转发到ss-tunnel监听的5353端口,ss-tunnel会将解析请求转发到远程服务器,通过远程服务器来解析域名。

iptables+ipset

iptablesipset主要用来区分国内流量和转发代理流量。

ipset

ipset.conf

1
2
3
4
5
1.0.1.0/24
1.0.2.0/23
1.0.8.0/21
1.0.32.0/19
...

shell:

1
2
ipset create chnroute hash:net
ipset -R < ipset.conf

上面代码创建了一个名为chnroute的IP集合。

iptables sample:
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
iptables -t nat -N SHADOWSOCKS
iptables -t mangle -N SHADOWSOCKS

# 直连服务器 IP
iptables -t nat -A SHADOWSOCKS -d [SS-SERVER-IP]/24 -j RETURN

# 允许连接保留地址
iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN

# 直连中国 IP
iptables -t nat -A SHADOWSOCKS -p tcp -m set --match-set chnroute dst -j RETURN
iptables -t nat -A SHADOWSOCKS -p icmp -m set --match-set chnroute dst -j RETURN

# 重定向到 ss-redir 端口
iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p udp -j REDIRECT --to-ports 1080
iptables -t nat -A OUTPUT -p tcp -j SHADOWSOCKS

# Apply the rules
iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS
iptables -t mangle -A PREROUTING -j SHADOWSOCKS

上面代码的主要含义是:

  • 先判断是不是请求远程$$服务流量,如果是则直接放行
  • 如果是请求内网的流量也会直接放行
  • 如果是请求大陆网站的流量,则直接放行
  • 如果上面的条件都不匹配,则会将流量转发到本机ss-local监听的1080端口

ss-redir

ss-redir会监听端口,并将代理请求转发到$$服务器

路由器透明代理实现方式

一般高端一点的路由器都可以通过刷机来实现,以华硕路由器为例:

梅林固件

梅林固件华硕路由器第三方固件,基于华硕官方固件。这种方式你需要自己搭建整套工具,虽然网上也有一些一键安装的脚本,但与我们上面提到的有一些出入。

官网: https://asuswrt.lostrealm.ca/

优点:开源,基于华硕官方固件,比较稳定。

缺点:

  • 需要熟悉linux
  • 需要自己搭建且坑比较多
  • 定制差
  • 除华硕路由器外,只支持部分非华硕路由器

梅林小宝

梅林小宝是基于梅林的固件,这个实现方式比较傻瓜式,刷机完成后可通过在软件中心安装shadowsocks,配置一下服务器信息就可以实现路由器透明代理。

官网:http://koolshare.cn/forum-96-1.html

优点:

  • 无需自己搭建
  • 有图形化管理界面

缺点:

  • 闭源,存在风险
  • 除华硕路由器外,只支持部分非华硕路由器

OpenWrt

OpenWrt是开源的路由器固件,他能提供一整套linux操作环境,插件众多且大多数插件都提供图形管理界面,大大降低而搭建难度。
当然在刷机之前你需要在Table of Hardware 里查一下你的路由器是否支持openwrt.

官网:https://openwrt.org/

优点:

  • 开源,维护者众多
  • 插件众多,很多定制功能:广告过滤,文件共享等。
  • 图形化管理界面
  • OpenWrt x86 支持X86平台,可实现软路由。

缺点:

  • 需要一点linux知识

路由器透明代理的不足

当然路由器透明代理也有其不足,路由器一般都是低功耗平台。以ac66u为例,大陆白名单模式下只能跑到30M的带宽,CPU占用已经是100%。

软路由

软路由顾名思义,就是在软件层面实现路由功能,基于x86平台,性能强大,解决硬路由性能不足的问题,这里就不多说了。

参考

利用shadowsocks打造局域网翻墙透明网关

dnsmasq gfwlist

China IP List

https://www.v2ex.com/t/503057

Debian jessie 安装 docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo apt-get remove docker docker-engine docker.io
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install docker-ce

Groovy JSON处理的一些细节

最近遇到一项目,需要在手机端存储用户数据,实现离线访问。其中用户数据处理的逻辑如下图:

User data flow

  1. 服务端从亚马逊S3上下载用户JSON文本数据库

  2. 反序列化用户数据

  3. 更新用户数据

  4. 将用户数据序列化为JSON文本

  5. 保存到亚马逊S3上

由于项目设计缺陷,用户所有的数据都存储一个Map对象里,导致Map对象过大,在项目运行过程中出现了内存不足的异常。为了解决内存不足问题,服务端采用了JacksonStreamingApi优化了JSON序列及反序列化步骤,避免将整个用户文件载入到内存中,至此内存不足的异常就再也没有发生。

其实这里有个问题,如果是用户数据过大,内存不足异常会在步骤3结束后就会发生,为什么偏偏在步骤4序列化为JSON时抛出呢?这里就要说到 Groovy的LazyMap了。

LazyMap代码:

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class LazyMap extends AbstractMap<String, Object> {

static final String JDK_MAP_ALTHASHING_SYSPROP = System.getProperty("jdk.map.althashing.threshold");

/* Holds the actual map that will be lazily created. */
private Map<String, Object> map;
/* The size of the map. */
private int size;
/* The keys stored in the map. */
private String[] keys;
/* The values stored in the map. */
private Object[] values;

public LazyMap() {
keys = new String[5];
values = new Object[5];
}
...

public Object put(String key, Object value) {
if (map == null) {
for (int i = 0; i < size; i++) {
String curKey = keys[i];
if ((key == null && curKey == null)
|| (key != null && key.equals(curKey))) {
Object val = values[i];
keys[i] = key;
values[i] = value;
return val;
}
}
keys[size] = key;
values[size] = value;
size++;
if (size == keys.length) {
keys = grow(keys);
values = grow(values);
}
return null;
} else {
return map.put(key, value);
}
}

public Object get(Object key) {
buildIfNeeded();
return map.get(key);
}

private void buildIfNeeded() {
if (map == null) {
// added to avoid hash collision attack
if (Sys.is1_8OrLater() || (Sys.is1_7() && JDK_MAP_ALTHASHING_SYSPROP != null)) {
map = new LinkedHashMap<String, Object>(size, 0.01f);
} else {
map = new TreeMap<String, Object>();
}

for (int index = 0; index < size; index++) {
map.put(keys[index], values[index]);
}
this.keys = null;
this.values = null;
}
}
}

从代码中可以看出:对于未进行过读操作(get,containsKey等)的LazyMap对象,keys和values分别存在了两个数组中,一旦调用了读取方法,LazyMap会将数组转化成Map对象,就是这一步操作引起了内存占用变化。

拿大小约为35MB的用户文件测试,反序列化后,内存中LazyMap对象为73MB(line 1),一旦对对象进行toJson操作(line 2),内存占用上升到了559MB(line 3)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    public static void main(String[] args) {
File jsonFile = new File('data-format.json')
Object obj = new JsonSlurper().parse(jsonFile) // LazyMap here
showSize(obj) // line 1
JsonOutput.toJson(obj) // line 2
showSize(obj) // line 3
}

static void showSize(obj) {
def size = ObjectSizeCalculator.getObjectSize(obj) / 1024 / 1024
println("Object memory size is $size MB")
}

// output logs:
Object memory size is 73.51363372802734375 MB
Object memory size is 559.32244873046875 MB

由于用户数据文件较大且嵌套了多层Map,加之JsonOutput.toJson方法会遍历LazyMap对象所有节点,相当于对所有节点进行了读操作,导致节点中的数组转换成Map对象,最终引起内存不足异常。

ASUS 66u 搭建透明代理

安装软件

1
2
3
4
5
6
7
8
9
10
/usr/sbin/entware-setup.sh

opkg install bind-dig
opkg install shadowsocks-libev-ss-redir
opkg install shadowsocks-libev-ss-tunnel
opkg install libc libssp libev libmbedtls libpcre libpthread libsodium haveged zlib libopenssl
opkg install ipset4

//ac66u only
opkg install iptables

配置ss-redir服务

修改配置文件

  1. vim /opt/etc/init.d/S22shadowsocks
  2. ss-local改为ss-redir
  3. 添加启动参数-b 0.0.0.0
  4. ENABLED值改为 yes,变成开机启动

修改shadowsocks.json

修改服务器IP,端口,加密码方式。

配置dnsmasq

创建配置文件

  • vim /jffs/configs/dnsmasq.conf.add
  • 添加conf-dir=/opt/etc/dnsmasq.d

创建目录

  • mkdir /opt/etc/dnsmasq.d/

  • 下载规则文件

1
2
cd /opt/etc/dnsmasq.d/
curl -O https://cokebar.github.io/gfwlist2dnsmasq/dnsmasq_gfwlist.conf

配置ss-tunnel服务

ss-tunnel主要用于解决dns污染的问题,dnsmasq会将解析请求转发到ss-tunnel

创建开机启动脚本

  • 转到目录/jffs/scripts/
  • 创建名为比如start-ss-tunnel.sh文件,内容如下:
1
2
3
#!/bin/sh

/opt/bin/ss-tunnel -c /tmp/mnt/onmp/entware/etc/shadowsocks.json -l 5353 -L 8.8.8.8:53 -u > /dev/null 2>&1 &

创建service-start文件

1
chmod +x service-start

/jffs/scripts/start-ss-tunnel.sh 加到service-start

至此ss-tunnel就能开机启动了

配置iptables

下载chnroute.txt

1
wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > /jffs/configs/chnroute.txt

生成ipset集合

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > /jffs/configs/chnroute.txt

ipset -N chnroute nethash

for ip in $(cat '/jffs/configs/chnroute.txt'); do
ipset -A chnroute $ip
done


ipset --save > /jffs/configs/ipset.conf

因为chnroute.txt文件比较大,生成会比较慢,故将生成的ipset保存到ipset.conf中,每次启动时从ipset.conf中导入IP.

启动脚本

SS启动脚本ss-up.sh

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
#!/bin/sh

alias iptables='/opt/sbin/iptables'

ipset -R < /jffs/configs/ipset.conf

# ipset -N chnroute iphash

# for ip in $(cat '/jffs/scripts/chnroute.txt'); do
# ipset -A chnroute $ip
# done

iptables -t nat -N SHADOWSOCKS
iptables -t mangle -N SHADOWSOCKS

# 直连服务器 IP
iptables -t nat -A SHADOWSOCKS -d [SS-SERVER-IP]/24 -j RETURN

# 允许连接保留地址
iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN

# 直连中国 IP
iptables -t nat -A SHADOWSOCKS -p tcp -m set --match-set chnroute dst -j RETURN
iptables -t nat -A SHADOWSOCKS -p icmp -m set --match-set chnroute dst -j RETURN

# 重定向到 ss-redir 端口
iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p udp -j REDIRECT --to-ports 1080
iptables -t nat -A OUTPUT -p tcp -j SHADOWSOCKS

# Apply the rules
iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS
iptables -t mangle -A PREROUTING -j SHADOWSOCKS

将其中的SS-SERVER-IP修改成你的服务器地址

创建post-mount文件

1
chmod +x post-mount

ss-up.sh加入

1
2
#!/bin/sh
/jffs/scripts/ss-up.sh

经测试只有将启动脚本加入到post-mount中对能开机启动,可能的原因是ss-up.sh中设及到挂载分区的访问。

停止脚本

1
2
3
4
5
6
#!/bin/sh
iptables -t nat -D OUTPUT -p icmp -j SHADOWSOCKS
iptables -t nat -D OUTPUT -p tcp -j SHADOWSOCKS
iptables -t nat -F SHADOWSOCKS
iptables -t nat -X SHADOWSOCKS
ipset -X chnroute

参考