Build Home Router with OpenWrt – Add shadowsocks

3 minute read

  • make menuconfig
  • Network » Web Servers/Proxies » shadowsocks-libev-config
  • Network » Web Servers/Proxies » shadowsocks-libev-ss-redir
  • Network » Web Servers/Proxies » shadowsocks-libev-ss-rules
  • Network » Web Servers/Proxies » shadowsocks-libev-ss-tunnel
  • Base system » dnsmasq-full
  • Network » Firewall » iptables-mod-conntrack-extra
  • Network » Firewall » ip6tables » ip6tables-mod-nat
  • LuCI » 3. Applications » luci-app-shadowsocks-libev

You may also want to add dig, which is very useful for dns debugging:

  • Network » IP Addresses and Names » bind-dig

Remember to deselect dnsmasq as this is conflicted with dnsmasq-full.

After menuconfig the following options will be added to .config:

+CONFIG_LIBSODIUM_MINIMAL=y
+CONFIG_PACKAGE_bind-dig=y
+CONFIG_PACKAGE_bind-libs=y
+# CONFIG_PACKAGE_dnsmasq is not set
+CONFIG_PACKAGE_dnsmasq-full=y
+CONFIG_PACKAGE_dnsmasq_full_auth=y
+CONFIG_PACKAGE_dnsmasq_full_conntrack=y
+CONFIG_PACKAGE_dnsmasq_full_dhcp=y
+CONFIG_PACKAGE_dnsmasq_full_dhcpv6=y
+CONFIG_PACKAGE_dnsmasq_full_dnssec=y
+CONFIG_PACKAGE_dnsmasq_full_ipset=y
+CONFIG_PACKAGE_dnsmasq_full_noid=y
+CONFIG_PACKAGE_ip-tiny=y
+CONFIG_PACKAGE_ip6tables-mod-nat=y
+CONFIG_PACKAGE_ipset=y
+CONFIG_PACKAGE_iptables-mod-conntrack-extra=y
+CONFIG_PACKAGE_iptables-mod-tproxy=y
+CONFIG_PACKAGE_kmod-ipt-conntrack-extra=y
+CONFIG_PACKAGE_kmod-ipt-ipset=y
+CONFIG_PACKAGE_kmod-ipt-nat6=y
+CONFIG_PACKAGE_kmod-ipt-raw=y
+CONFIG_PACKAGE_kmod-ipt-tproxy=y
+CONFIG_PACKAGE_kmod-nf-conntrack-netlink=y
+CONFIG_PACKAGE_kmod-nf-nat6=y
+CONFIG_PACKAGE_kmod-nfnetlink=y
+CONFIG_PACKAGE_libcares=y
+CONFIG_PACKAGE_libev=y
+CONFIG_PACKAGE_libgmp=y
+CONFIG_PACKAGE_libipset=y
+CONFIG_PACKAGE_libmbedtls=y
+CONFIG_PACKAGE_libmnl=y
+CONFIG_PACKAGE_libnetfilter-conntrack=y
+CONFIG_PACKAGE_libnettle=y
+CONFIG_PACKAGE_libnfnetlink=y
+CONFIG_PACKAGE_libpcre=y
+CONFIG_PACKAGE_libsodium=y
+CONFIG_PACKAGE_luci-app-shadowsocks-libev=y
+CONFIG_PACKAGE_resolveip=y
+CONFIG_PACKAGE_shadowsocks-libev-config=y
+CONFIG_PACKAGE_shadowsocks-libev-ss-redir=y
+CONFIG_PACKAGE_shadowsocks-libev-ss-rules=y
+CONFIG_PACKAGE_shadowsocks-libev-ss-tunnel=y

Test shadowsocks acount

Before proceding, we need to setup a shadowsocks server or buy a ss account, fortunately, I found a very greate site that update free shadowsocks accounts regularly. free-ss-acount

To make sure these accounts works, we need a ss client installed on our smart phone, download shadowsocks-android for android phones. ss-android

Setup gfwlist for dnsmasq

Use gfwlist with dnsmasq to resolve dns issue, cokebar wrote a script to convert gfwlist to dnsmasq config:

./gfwlist2dnsmasq.sh -p 5353 -o gfwlist.conf

NOTE

  • The port number in gfwlist must be the same port set in ss_tunnel(local_port).
  • Replace dnsmasq with dnsmasq-full to have ipset support.

Copy generated config file to /etc/dnsmasq.d/ and specify with conf-dir=/etc/dnsmasq.d in /etc/dnsmasq.conf and add rules to /etc/firewall.user:

+ipset -N gfwlist iphash
+iptables -t nat -A PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080
+iptables -t nat -A OUTPUT -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1100

Configuration

By default, luci web interface have some instances that are not used for my case, remove ss_local, ss_server, ss_redir.hj, config Local instances, Remote Servers and Redir Rules like this:

Local Instances Redir Rules Remote Servers I don’t know what’s the meaning of Key (based64 encoding), but leave it blank is ok, will check this later.

Keep the remaining part untouched, then click Save & Apply, the configurations will be saved in /etc/config/shadowsocks-libev:

config ss_redir 'hi'
	option server 'sss0'
	option local_address '0.0.0.0'
	option local_port '1100'
	option mode 'tcp_and_udp'
	option timeout '60'
	option fast_open '1'
	option verbose '1'
	option reuse_port '1'
	option disabled 'false'

config ss_rules 'ss_rules'
	option redir_tcp 'hi'
	option redir_udp 'hi'
	option src_default 'checkdst'
	option dst_default 'bypass'
	list dst_ips_forward '8.8.8.8'
	option local_default 'bypass'
	list ifnames 'br-lan'
	list src_ips_forward '192.168.1.0/24'

config server 'sss0'
	option method 'aes-256-cfb'
	option server '185.134.21.41'
	option server_port '11135'
	option password 'edgkeb'

config ss_tunnel
	option mode 'tcp_and_udp'
	option timeout '60'
	option verbose '1'
	option server 'sss0'
	option tunnel_address '8.8.4.4:53'
	option local_port '5353'

Debugging

If all the above set up properly, the router should be working, connect phone or laptop to the router and see if we can watch youtube video, if not use dig to see if dns got resolved correctly:

root@OpenWrt:/# dig www.youtube.com

; <<>> DiG 9.11.5-P1 <<>> www.youtube.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40508
;; flags: qr rd ra; QUERY: 1, ANSWER: 17, AUTHORITY: 0, ADDITIONAL: 1

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

;; ANSWER SECTION:
www.youtube.com.	21599	IN	CNAME	youtube-ui.l.google.com.
youtube-ui.l.google.com. 299	IN	A	64.233.166.91
youtube-ui.l.google.com. 299	IN	A	64.233.166.136
youtube-ui.l.google.com. 299	IN	A	74.125.133.190
youtube-ui.l.google.com. 299	IN	A	74.125.133.93
youtube-ui.l.google.com. 299	IN	A	74.125.133.136
youtube-ui.l.google.com. 299	IN	A	64.233.167.93
youtube-ui.l.google.com. 299	IN	A	64.233.167.136
youtube-ui.l.google.com. 299	IN	A	64.233.167.190
youtube-ui.l.google.com. 299	IN	A	74.125.140.93
youtube-ui.l.google.com. 299	IN	A	74.125.140.190
youtube-ui.l.google.com. 299	IN	A	74.125.140.91
youtube-ui.l.google.com. 299	IN	A	74.125.140.136
youtube-ui.l.google.com. 299	IN	A	108.177.15.91
youtube-ui.l.google.com. 299	IN	A	108.177.15.93
youtube-ui.l.google.com. 299	IN	A	108.177.15.136
youtube-ui.l.google.com. 299	IN	A	108.177.15.190

;; Query time: 313 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jan 31 16:02:45 UTC 2019
;; MSG SIZE  rcvd: 334

If not, make sure netstat can see udp lines:

root@OpenWrt:/# netstat -nlp|grep ss
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:5353            0.0.0.0:*               LISTEN      3232/ss-tunnel
tcp        0      0 0.0.0.0:1100            0.0.0.0:*               LISTEN      3231/ss-redir
udp        0      0 0.0.0.0:45570           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:60942           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:49169           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:57396           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:1100            0.0.0.0:*                           3231/ss-redir
udp        0      0 0.0.0.0:50300           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:53379           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:58005           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:43705           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:60690           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:48465           0.0.0.0:*                           3232/ss-tunnel
udp        0      0 0.0.0.0:35174           0.0.0.0:*                           3232/ss-tunnel

I got ss not working two times(still don’t know why), and restart ss makes it works:

/etc/init.d/shadowsocks-libev restart