网站首页 文章专栏 树莓派搭建docker openvpn以及ipv6隧道
树莓派搭建docker openvpn以及ipv6隧道
创建于:2019-08-17 06:11:07 更新于:2024-12-26 16:19:03 羽瀚尘 6319
vpn

简介

openvpn可以方便地穿越nat,是替代pptp的好工具。但是openvpn也有配置证书的步骤繁多的难点,本文主要介绍几种安装openvpn的方法,以及ipv6 in ipv4的方法(客户端通过openvpn获取ipv6地址并上网)

本文介绍的方法同样适用于x86 amd64设备。

最简方法

最简单的方法当然是docker,在树莓派中先安装docker,然后下载openvpn的镜像

docker pull giggio/openvpn-arm

设置一个本地存储

OVPN_DATA="/home/wenfeng/ovpn-data"

生成ca

VPN.SERVERNAME.COM是你的服务器域名或者ip地址

docker run -v $OVPN_DATA:/etc/openvpn --rm giggio/openvpn-arm ovpn_genconfig -u udp://VPN.SERVERNAME.COM
docker run -v $OVPN_DATA:/etc/openvpn --rm -it giggio/openvpn-arm ovpn_initpki nopass

运行服务进程

docker run -v $OVPN_DATA:/etc/openvpn -d --name openvpn -p 1194:1194/udp --cap-add=NET_ADMIN giggio/openvpn-arm

为客户端生成证书

CLIENTNAME是自定义的客户端名称。

docker run -v $OVPN_DATA:/etc/openvpn --rm -it giggio/openvpn-arm easyrsa build-client-full CLIENTNAME nopass

将证书从container中取出

docker run -v $OVPN_DATA:/etc/openvpn --rm giggio/openvpn-arm ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn

如果不出意外,openvpn服务端已经搭建起来了

手工安装

手工安装即不借助docker,在裸机上安装openvpn服务器。可以参考ubuntu安装openvpn的方法,在树莓派上安装openvpn(这篇文章中很多都在讲证书的生成,openvpn的配置倒是很少)。

所以我们可以考虑使用docker openvpn中生成的ca与证书,以及配置文件来启动本地的openvpn server,可以省很多力气。

使用下面的脚本将docker的配置文件放到本地

sudo rm /etc/openvpn
sudo ln -s /home/wenfeng/ovpn-data /etc/openvpn

其实就是做了个软连接,配置文件通用。

系统启动时使用sudo systemctl start openvpn@openvpn的方法,这个@挺特别,后面跟着自己的配置文件名称(去除后缀)。这意味着我们可以有很多配置文件,通过@setting_name来选择。

如果出错,建议用sudo /usr/sbin/openvpn --status /run/openvpn/openvpn.status 10 --cd /etc/openvpn --config /etc/openvpn/openvpn.conf,观察输出log

增加ipv6支持

因为docker container中没有ipv6地址(应该没有),ipv6 in ipv4 只能在裸机上进行。

转发ipv6包

修改/etc/sysctl.conf文件

net.ipv4.ip_forward=1  
    ...
net.ipv6.conf.all.forwarding=1  
net.ipv6.conf.all.proxy_ndp = 1  

设置iptables

注意修改为你自己的ip地址

iptables -t nat -A POSTROUTING -s 10.11.0.0/16 -j SNAT --to 172.16.8.1  

修改openvpn配置文件

服务器端server.conf中的相关配置:


# Server mode and client subnets
server 10.8.0.0 255.255.255.0  
server-ipv6 aaaa:bbbb:cccc:dddd:80::/112  
topology subnet

# IPv6 routes
push "route-ipv6 aaaa:bbbb:cccc:dddd::/64"  
push "route-ipv6 2000::/3"

修改aaaa:bbbb:cccc:dddd为你的真实网址前缀。

为客户端增加proxy

ipv4包由iptables 进行nat,ipv6包是proxy。 先在客户端查看ipv6地址,然后运行下面命令。

sudo /sbin/ip -6 neigh add proxy aaaa:bbbb:cccc:dddd:80::1002  dev eth0

aaaa:bbbb:cccc:dddd:80::1002修改为你自己的ip地址,eth0修改为你自己的网卡。

测试ipv6

客户端ping通openvpn服务器网关

ping6 aaaa:bbbb:cccc:dddd:80::1

用curl测试ipv6网站

curl -g -6 https://www.google.com.hk

自动添加ipv6 proxy

服务器端server.conf配置

# Run client-specific script on connection and disconnection
script-security 2  
client-connect "/etc/openvpn/up.sh"  
client-disconnect "/etc/openvpn/down.sh"

这里的script-security 2很重要,不设置会出现WARNING: External program may not be called unless '--script-security 2' or higher is enabled.

这里的up.shdown.sh可以在这里找到,但是我试了之后缺少环境变量,所以目前仍是手工设置ipv6 proxy,研究中。

排错方法

系统一般提示通过journalctl -xe或者systemctl status来排错,但是这两项并不能给出有效信息。

server端无法启动服务,又找不到出错信息 启动服务时出现错误:

pi@raspberrypi:~ $ sudo service openvpn@server start
Job for openvpn@server.service failed because the control process exited with error code.
See "systemctl status openvpn@server.service" and "journalctl -xe" for details.

journalctl -xe返回的结果

<pre>- The unit openvpn@server.service has entered the &apos;failed&apos; state with result &apos;exit-code&apos;.
Jul 26 17:27:15 raspberrypi systemd[1]: <font color="#EF2929"><b>Failed to start OpenVPN connection to server.</b></font>
-- Subject: A start job for unit openvpn@server.service has failed
</pre>

systemctl status openvpn@server.service返回的结果,都没有有效的错误信息,只是告诉你出错了。

● openvpn@server.service - OpenVPN connection to server
   Loaded: loaded (/lib/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
   Active: activating (auto-restart) (Result: exit-code) since Fri 2019-07-26 17:28:21 CST; 509ms ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
  Process: 13082 ExecStart=/usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openv
 Main PID: 13082 (code=exited, status=1/FAILURE)

所以我想可以将后台程序变成前台方式,来查看log排错。 将下面命令中的--config换为自己的配置文件即可

sudo /usr/sbin/openvpn --status /run/openvpn/openvpn.status 10 --cd /etc/openvpn --config /etc/openvpn/openvpn.conf

错误1:no such openssl.h

发现在./build-ca时报错

no such openssl.cnf

查看脚本发现,easy-rsa自己带了三个不同版本的openssl.cnf,唯独没有系统中的1.1.0版本的,无奈打算将树莓派的openssl降级到1.0.0

使用apt-cache madison openssl发现没有低版本的,只能自己手动编译。

树莓派编译openssl, 源码下载地址下载地址

错误2:客户端无法上网

现象: 客户端正常连接服务端,并且两者互相可以ping通,客户端甚至可以请求服务端自己的http服务数据,但就是无法请求其他数据,例如www.baidu.com

测试1: 使用下面的命令请求数据:

curl www.baidu.com --interface tun0

会在很长时间后显示time out

测试2: 使用下面的命令ping外网主机

ping 220.181.38.149 -I tun0

没有响应,100% loss

用下面的命令对tun0抓包(客户端运行)

sudo tcpdump -v  -i tun0

抓包结果如下:

22:28:14.638190 IP (tos 0x0, ttl 64, id 35007, offset 0, flags [DF], proto ICMP (1), length 84)
    10.8.0.6 > 220.181.38.149: ICMP echo request, id 18716, seq 1, length 64
22:28:14.645933 IP (tos 0x0, ttl 52, id 35007, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.149 > 10.8.0.6: ICMP echo reply, id 18716, seq 1, length 64
22:28:15.643038 IP (tos 0x0, ttl 64, id 35227, offset 0, flags [DF], proto ICMP (1), length 84)
    10.8.0.6 > 220.181.38.149: ICMP echo request, id 18716, seq 2, length 64
22:28:15.650823 IP (tos 0x0, ttl 52, id 35227, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.149 > 10.8.0.6: ICMP echo reply, id 18716, seq 2, length 64
22:28:16.667028 IP (tos 0x0, ttl 64, id 35436, offset 0, flags [DF], proto ICMP (1), length 84)
    10.8.0.6 > 220.181.38.149: ICMP echo request, id 18716, seq 3, length 64
22:28:16.677797 IP (tos 0x0, ttl 52, id 35436, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.149 > 10.8.0.6: ICMP echo reply, id 18716, seq 3, length 64
22:28:17.691232 IP (tos 0x0, ttl 64, id 35689, offset 0, flags [DF], proto ICMP (1), length 84)
    10.8.0.6 > 220.181.38.149: ICMP echo request, id 18716, seq 4, length 64
22:28:17.701566 IP (tos 0x0, ttl 52, id 35689, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.149 > 10.8.0.6: ICMP echo reply, id 18716, seq 4, length 64
22:28:18.715232 IP (tos 0x0, ttl 64, id 35725, offset 0, flags [DF], proto ICMP (1), length 84)
    10.8.0.6 > 220.181.38.149: ICMP echo request, id 18716, seq 5, length 64
22:28:18.723667 IP (tos 0x0, ttl 52, id 35725, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.149 > 10.8.0.6: ICMP echo reply, id 18716, seq 5, length 64
22:28:19.716722 IP (tos 0x0, ttl 64, id 35833, offset 0, flags [DF], proto ICMP (1), length 84)
    10.8.0.6 > 220.181.38.149: ICMP echo request, id 18716, seq 6, length 64
22:28:19.731483 IP (tos 0x0, ttl 52, id 35833, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.149 > 10.8.0.6: ICMP echo reply, id 18716, seq 6, length 64

可知对方主机正常响应,openvpn服务器正常,但是客户端主机自己不正常,无法将网络层的数据反馈到应用层。怀疑是iptables有误,全部清空后错误照常。

使用命令ip route show查看网关 修改前的网关

default via 10.135.0.1 dev wlp4s0b1  proto static  metric 600
10.8.0.1 via 10.8.0.5 dev tun0
10.8.0.5 dev tun0  proto kernel  scope link  src 10.8.0.6
10.134.118.131 via 10.135.0.1 dev wlp4s0b1  src 10.135.80.126
10.135.0.0/16 dev wlp4s0b1  proto kernel  scope link  src 10.135.80.126  metric 600
169.254.0.0/16 dev wlp4s0b1  scope link  metric 1000
192.168.19.0/24 dev enp3s0  proto kernel  scope link  src 192.168.19.1  metric 100
192.168.194.0/24 dev ztyourshd4  scope link
192.168.194.0/24 dev ztyourshd4  proto kernel  scope link  src 192.168.194.5

查看tun0配置 ifconfig

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.8.0.6  P-t-P:10.8.0.5  Mask:255.255.255.255
          inet6 addr: fe80::15d6:6be6:afbd:cb5/64 Scope:Link
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:625 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3293 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:114339 (114.3 KB)  TX bytes:445127 (445.1 KB)

新增网关

sudo route add default gw 10.8.0.5

这里不能用10.8.0.1做网关,如果添加该地址为网关,会有如下错误:

SIOCADDRT: Network is unreachable

(可选)如果域名服务不正常,需要手动更改

修改这个文件即改即用

vim /etc/resolv.conf
cat /etc/resolv.conf

修改后

nameserver 8.8.8.8

参考https://blog.csdn.net/u012732259/article/details/76502231

设置好默认网关后,ping正常,网络访问正常。

参考

TODO

  • [ ] 自动设置ipv6 proxy