记录时间:2020 年 1 月 26 日

关键词:Padavan golang 交叉编译 wireguard

注意这是一次失败记录,虽然成功地编译出了wireguard-go和 tools,但是编译出的文件体积太大装不进K2路由器,不能测试其是否可用,也不想搞了,因为OpenWrt体积更小使用也简单,稳定性方面也超出我的预期,所以之后换用OpenWrt了。另外再说一下,wg体积小性能稳,对于家庭的组网来说很好用。

注:本记录仅为学习!关于使用请遵守相关规定!

在Ubuntu编译

  1. 准备编译环境

编译系统为 Ubuntu 18.04,首先安装必要的软件包

1
2
3
4
5
6
7
8
9
sudo apt update
sudo apt-get install build-essential pkg-config cmake autoconf automake libtool wget git
#编译libmnl
cd /tmp
git clone git://git.netfilter.org/libmnl
cd /tmp/libmnl/
./autogen.sh --disable-shared --host=mipsel-linux-uclibc
./configure
make
  1. 编译wireguard-tools
    1
    2
    3
    4
    cd ~
    git clone https://github.com/WireGuard/wireguard-tools.git
    cd wireguard-tools/src/
    env CFLAGS=-I/tmp/libmnl/include LDFLAGS=-L/tmp/libmnl/src/.libs make
  2. 安装go
    1
    2
    3
    4
    5
    6
    #这里安装了golang版本为1.13.7
    wget -O /tmp/golang.tar.gz https://dl.google.com/go/go1.13.7.linux-amd64.tar.gz
    tar -C /usr/local -xvzf /tmp/golang.tar.gz
    export PATH=$PATH:/usr/local/go/bin
    #启用阿里云go镜像加速下载
    export GOPROXY="https://mirrors.aliyun.com/goproxy/"
  3. 编译wireguard-go
    1
    2
    3
    4
    5
    mkdir -p $HOME/gobuild/ && cd $HOME/gobuild/
    git clone https://github.com/WireGuard/wireguard-go.git
    cd wireguard-go
    export GOPATH="$HOME/gobuild/"
    env GOOS=linux GOARCH=mipsle go build -v -o "wireguard-go"
  4. 复制wg和wireguard-go到主目录,就可以在主目录中找到了
    1
    2
    cp $HOME/wireguard-tools/src/wg $HOME
    cp $HOME/gobuild/wireguard-go/wireguard-go $HOME

    直接用github actions自动编译(特别推荐)

    贼省事,不多解释了,直接上脚本。由于没有仔细了解脚本语法,因此这个脚本是简单修改来的可能有不合理的地方,另外要注意一下随着源码的不断更新,脚本可能会在未来失效。关于使用可以参考一下前面的捯饬记录
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
name: Build wireguard-go for Padavan

on: 
  push:
    branches: 
      - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: 初始化
      env:
        DEBIAN_FRONTEND: noninteractive
      run: |
        #sudo apt-get update
        wget -O /tmp/golang.tar.gz https://dl.google.com/go/go1.13.7.linux-amd64.tar.gz
        sudo tar -C /usr/local -xvzf /tmp/golang.tar.gz
        export PATH=$PATH:/usr/local/go/bin
    - name: 编译wireguard-go
      run: |
        mkdir -p /tmp/gobuild/ && cd /tmp/gobuild/
        git clone https://git.zx2c4.com/wireguard-go
        cd wireguard-go
        export GOPATH="/tmp/gobuild/"
        env GOOS=linux GOARCH=mipsle go build -v -o "wireguard-go"
    - name : 上传wireguard-go
      uses: actions/upload-artifact@master
      with:
        name: wireguard-go
        path: /tmp/gobuild/wireguard-go/wireguard-go
    - name: 编译wireguard-tools
      run: |
        cd /tmp
        git clone https://git.zx2c4.com/wireguard-tools
        git clone git://git.netfilter.org/libmnl
        cd /tmp/libmnl/
        ./autogen.sh --disable-shared --host=mipsel-linux-uclibc
        ./configure
        make
        cd /tmp/wireguard-tools/src/
        env CFLAGS=-I/tmp/libmnl/include LDFLAGS=-L/tmp/libmnl/src/.libs make        
    - name : 上传wireguard-tools
      uses: actions/upload-artifact@master
      with:
        name: wireguard-tools
        path: /tmp/wireguard-tools/src/wg

关于wg文件的使用

因为不能测试,也就没有做进一步的了解。官方的简单说明中关于wireguard-tools都是直接编译安装,对单个wg的使用可能需要啃一下官方的文档,或者了解一下make install来手动配置,应该也挺麻烦的吧。

简单记录一下使用docker来编译的过程

在docker容器中编译(前提是安装了docker),因为我的Ubuntu里装了很多乱七八糟的东西,为了保持干净还是选择用docker来编译,但是没有特地做新的镜像,所以容器里的环境是从头开始搭的。

  1. 启动一个docker ubuntu容器
    1
    sudo docker run -it --rm ubuntu
  2. 安装必要的软件,切换软件源加速后续下载
    1
    2
    3
    4
    apt update
    apt install -y apt-transport-https ca-certificates
    sed -i 's#http://archive.ubuntu.com#https://mirrors.huaweicloud.com#' /etc/apt/sources.list
    sed -i 's#http://security.ubuntu.com#https://mirrors.huaweicloud.com#' /etc/apt/sources.list
  3. 中间编译步骤和上边 在ubuntu编译 是一样的
  4. 编译完成后另开一个终端窗口,执行以下命令复制wg和wireguard-go到本机
    1
    2
    sudo docker cp <container>:/root/wireguard-tools/src/wg wg
    sudo docker cp <container>:/root/gobuild/wireguard-go/wireguard-go wireguard-go
    使用完毕后ctrl + d退出容器,不留痕迹!

    END

    经过这次捯饬才发现Padavan的缺点:Linux版本有点低(3.4),而且模块化程度低,真想捯饬还得是OpenWrt。另外一个wireguard-go体积达到了4M,这K2就很吃力啊,由于这些原因还是转向了OpenWrt。经过短暂的试用感觉官方版OpenWrt 19.07的稳定性表现超出了我的预期,所以Padavan的内容到这里应该就告一段落了,哎希望给能看到这些个记录的带来一点点启发。不说了,IPv6我来了!

参考

Compiling the Kernel Module from Source:https://www.wireguard.com/compilation/

Installing WireGuard on ASUS RT-N56U (Padavan):https://medium.com/@yjwong/installing-wireguard-on-asus-rt-n56u-731c22f1f5bd

Go 语言跨平台路由器编译:https://blog.lutty.me/code/2017-04/golang-cross-compile-openwrt-ddwrt-build.html

记录时间:2020 年 1 月 16 日

关键词:GitHub Action Padavan 自动编译 云编译 固件 K2

在之前搜索Padavan的编译教程时,发现了openwrt固件的在线自动编译,当时觉得很厉害。在捯饬完Padavan的固件编译之后,想找找看Padavan有没有类似的东西,直接在GitHub上搜索就找到了,地址:https://github.com/chongshengB/Padavan-build,感谢chongshengB。

简单的试用

由于打开页面时没有任何说明,于是直接fork了这个脚本,根据openwrt的自动编译教程以及这个编译脚本的内部注释,简单试用了一下一次就编译通过了,非常方便快捷,但是脚本默认编译的是K2P的固件没法测试。

简单说一下脚本的使用方法:

  1. fork这个脚本
  2. 打开Actions页面,点击绿色的 I understand my workflows, go ahead and run them
  3. 返回Code页面,打开.github/workflows,再打开build-padavan.yml文件,删除如下这几行中的#之后提交保存,编译就会开始自动运行,在Actions页面还能看到编译进度
  4. 编译完成后,再次打开Actions, 点击右上方的Artifacts就能看到下载的链接了
    1
    2
    3
    4
    5
    6
      #  branches: 
      #    - master
    #  schedule:
    #    - cron: 0 8 * * 5
     # watch:
     #   types: [started]

    尝试自动编译一个K2的固件

  5. 找到build-padavan.yml文件中第48行中的TNAME: K2P-5.0,修改为
    1
    TNAME: PSG1218
  6. 按脚本注释删除和添加配置项,关于配置项,可以查看配置文件
    1
    2
    3
    4
    5
    6
    #因不同型号配置功能不一样,所以先把配置项删除,如果你自己要添加其他的,也要写上删除这一条,切记!!!
    sed -i '/CONFIG_FIRMWARE_INCLUDE_MENTOHUST/d' .config #删除配置项MENTOHUST
    sed -i '/CONFIG_FIRMWARE_INCLUDE_SCUTCLIENT/d' .config #删除配置项SCUTCLIENT
    #以下选项是定义你需要的功能(y=集成,n=忽略),重新写入到.config文件
    echo "CONFIG_FIRMWARE_INCLUDE_MENTOHUST=n" >> .config #MENTOHUST
    echo "CONFIG_FIRMWARE_INCLUDE_SCUTCLIENT=n" >> .config #SCUTCLIENT
  7. 保存并重新上传该脚本,Actions就开始自动编译步骤了,编译完成后在Artifacts中下载编译完成的固件

    END

    其实自动编译过程就是将手动编译时的每个步骤写成了脚本,GitHub Actions会根据脚本来运行每条命令,非常方便。甚至可以利用Actions和GitHub page方便地搭建博客,总之使用方法多样,另外在这个Marketplace还能找到很多别人写好的Actions,实现很多有趣的功能。关于GitHub Actions 详细的内容可以参考一下官方文档

记录时间:2020 年 1 月 8 日

关键词:Padavan IPV6 DDNS 邮件 脚本 stateless

START

想要体验一下拥有公网 IPV6 的便捷,无奈家庭宽带的 IP 都是动态分配的,为了方便使用只好找个 DDNS,本文采用的是 dynv6 提供的免费 DDNS 和二级域名。顺便说一下,Padavan 内置的 DDNS 貌似无法使用,那就只好用脚本来解决了。

更新:不多赘述,具体查看这两个帖子 家庭宽带 私设 web 被检测 魔都电信被停宽带应对家宽 Web 的收紧,讨论一下在外网控制家庭设备的方案,因此不再推荐自家家用用途采取DDNS的方法!推荐用邮件或其他方式获取ip,采用ip来访问,邮件脚本见下文。

使用脚本配置 DDNS

使用前提

本文使用到的脚本适用于下图中的这种情况,WAN IP 与 LAN IP 都为无状态分配(stateless),并且 pppoe 也在此路由器上进行,其他的路由配置情况没有测试,待测试后再来更新。

图片

路由器和下级设备的 DDNS

注意!该脚本仅更新临时地址,不支持其他类型地址。另外本脚本的IPV6地址直接使用ip命令和NDP获取,除了发送邮件外不会连接任何第三方服务器。

  1. 什么方法都可以,只要把脚本文件放进路由器即可,这里以简单的winscp举例:用winscp连接到路由器,然后在/etc/storage目录下新建一个名为dynv6.sh的文本文件,复制以下脚本,并修改填写你的token信息。
    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
    #!/bin/bash -e
    #脚本使用方法
    #./dynv6.sh [mode] [hostname] [name] [mac]    # mode: router or neigh

    ########填写dynv6的token信息#######
    token=xxxxxxxxxxxx
    #获取参数
    mode=$1
    hostname=$2
    name=${3:-'Router'}
    mac=$4
    #有必要的话更改网络设备名
    device=ppp0

    #模式选择错误处理
    if [ "$mode" != "router" -a "$mode" != "neigh" ]; then
      echo "please select router or neigh"
      exit
    fi
    #neigh模式处理下级设备IP
    if [ "$mode" = "neigh" ]; then
      if [ -z $mac ]; then
        echo "mac is empty"
        exit
      fi
      mac=$( echo $mac | tr '[A-Z]' '[a-z]' )
      file=$HOME/.dynv6.neigh.$name
      [ -e $file ] && old=`cat $file`
      #获得下级设备的ip
      macinf=$(echo $mac | tr '[A-Z]' '[a-z]' | awk  -F ':'  '{print $5$6}' )
      ipaddress=$(ip -6 neighbor | grep $mac | grep -v $macinf | grep -v 'fe80' | awk '{print $1}')

      #router模式处理路由器IP
      else
      file=$HOME/.dynv6.router
      [ -e $file ] && old=`cat $file`
      #获取ip地址
      ipaddress=$(ip -6 addr list scope global $device | grep "global" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p')
    fi

    #判断ip地址是否存在
    if [ -z "$ipaddress" ]; then
      echo "no IPv6 address found"
      exit 1
    fi
    #检查地址是否改变
    if [ "$old" = "$ipaddress" ]; then
      echo "IPv6 address unchanged"
      exit
    fi

    #发送新的ipv6地址到dynv6
    curl -s -S -f -k "https://dynv6.com/api/update?hostname=$hostname&ipv6=$ipaddress&token=$token"

    #缓存当前ip地址到文件
    echo $ipaddress > $file

    #打印系统日志
    logger 监测到设备 $name 的IPv6变更, dynv6 DDNS已完成同步
  2. 用ssh连接到路由器,对脚本文件添加可执行权限,保存已有的计划任务
    1
    2
    3
    cd /etc/storage
    chmod +x dynv6.sh
    crontab -l > dynv6cron
  3. 添加需要进行 DDNS 的设备,每 10 分钟自动执行一次检查。注意!把命令中的域名改为你的域名,比如 xxxx.dynv6.net,设备名自定但必须是英文否则会出错,MAC 地址要求按照带有冒号分隔符的格式,例如xx:xx:xx:xx:xx:xx
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #参数格式说明:./dynv6.sh [模式] [域名] [设备名] [MAC地址]
    cat >> dynv6cron <<EOF
    #添加路由器的DDNS
    */10 * * * * /etc/storage/dynv6.sh router 域名
    #添加下级设备的DDNS
    */10 * * * * /etc/storage/dynv6.sh neigh 域名 设备名 MAC地址
    # ......
    EOF
    #可以添加多个设备,每一行对应一个设备
    #举例如下
    #*/10 * * * * /etc/storage/dynv6.sh router xxx.dynv6.net
    #*/10 * * * * /etc/storage/dynv6.sh neigh xxxx.dynv6.net phone 11:22:33:aa:bb:cc
  4. 启动计划任务
    1
    crontab dynv6cron
  5. 在 Padavan 的后台管理页找到高级设置->自定义设置->脚本->在 WAN 上行/下行启动后执行中添加以下命令,就可以在重启路由后立即更新地址。
    1
    2
    3
    4
    #对于路由器
    /etc/storage/dynv6.sh router 域名
    #或者是下级设备
    /etc/storage/dynv6.sh neigh 域名 设备名 MAC地址

    使用邮件的方式获得当前 IPV6 地址

    在搜集相关问题时,看到了这篇 《IPV6网络下建立安全的家庭服务器[NAS]》 ,其中

在 ipv6 下,由于不再只分配一个 ip 地址,而是一下子给了你海量的 ipv6 地址,这就形成了天然的安全屏障。大家都知道,要尝试对某个家庭服务器发起攻击尝试,首要的条件就是知道对方的服务器地址。

最大的安全是什么,你的服务器 ipv6 地址只有你自己知道,如果你不对家庭服务器捆绑 DDNS(动态域名),那么有心人即使知道了你家宽带今天 ipv6 的 64 位前缀,为了尝试获得服务器的真实 ipv6 地址,它需要对 16 亿亿个 ipv6 地址进行扫描,再牛的黑客,没有几年的时间是无法完成的。而你的 ipv6 地址一般每 3 天更换一次前缀,意味着黑客必须在 3 天内完成 16 亿亿个有效扫描,这是无法完成的任务。
而如果你捆绑了动态域名,这就好比直接打开了你家 ipv6 网络的一道门,任何人只要知道你的动态域名,根本不需要扫描,就可以直接知道你服务器的 ipv6 地址,然后进行攻击尝试。
由于家庭服务器,一般只为有限的家庭成员提供服务,因此服务器地址只需要家人能够解析就可以,因此通过服务器端发送邮件,用户直接在软件里自动通过电子邮件进行解析的方式,可以极大的保护建立在动态 ipv6 地址上的家庭服务器不被泄漏。
使用这种方式,黑客要获取服务器 ipv6 地址,就必须尝试获取邮件,而电子邮箱由于是需要用户名和口令才能登录,而破解大公司的邮箱服务器口令和用户名是非常非常的困难。也就是通过电子邮件解析服务器地址的方法,对比使用动态域名,多了一道由电子邮箱提供的安全防火门,让你家的服务器 ip 地址真正大隐隐于市了。

总结一下就是,使用 DDNS 域名一旦泄露被公布在互联网上,受到精准攻击的风险就会上升,因此直接使用动态变化的 IP 会安全一些。当然这只是针对自家家用用途,如果要对外提供服务还得上 DDNS。(下级设备可以使用 DHCPv6 stateful 有状态分配 ip,不推荐 EUI64 地址)

自动发送新的 IP 到指定邮箱

  1. 用winscp在路由器中的/etc/storage目录下,新建一个文件名为mailuip.sh的文本文件,复制脚本内容如下,务必填写SMTP的配置信息
    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #!/bin/bash -e
    #脚本使用方法
    #./mailuip.sh [mode] [name] [mac]

    #SMTP配置   #(例子)
    #SMTP服务器#smtpserver=smtp.126.com
    #邮箱账号#fromaddress=xxxxxx@126.com
    #邮箱密码fromaddresspwd=xxxxxxxxxxxxx
    #收件人信息#toaddress=xxxxxx@qq.com 多个收件人用英文逗号分隔

    #SMTP配置
    smtpserver=
    fromaddress=
    fromaddresspwd=
    toaddress=

    #参数配置
    mode=$1
    name=${2:-'Router'}
    mac=$3
    #有必要的话更改网络设备名
    device=ppp0

    #模式选择错误处理
    if [ "$mode" != "router" -a "$mode" != "neigh" ]; then
      echo "please select router or neigh mode"
      exit
    fi
    #neigh模式处理下级设备IP
    if [ "$mode" = "neigh" ]; then
      if [ -z $mac ]; then
        echo "mac is empty"
        exit
      fi
      mac=$( echo $mac | tr '[A-Z]' '[a-z]' )
      file=$HOME/.mailuip.neigh.$name
      [ -e $file ] && old=`cat $file`
      #获得下级设备的ip
      macinf=$(echo $mac | tr '[A-Z]' '[a-z]' | awk  -F ':'  '{print $5$6}' )
      ipaddress=$(ip -6 neighbor | grep $mac | grep -v $macinf | grep -v 'fe80' | awk '{print $1}')

      #router模式处理路由器IP
      else
      file=$HOME/.mailuip.router
      [ -e $file ] && old=`cat $file`
      #获取ip地址
      ipaddress=$(ip -6 addr list scope global $device | grep "global" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p')
    fi

    #判断ip地址是否存在
    if [ -z "$ipaddress" ]; then
      echo "no IPv6 address found"
      exit 1
    fi
    #检查地址是否改变
    if [ "$old" = "$ipaddress" ]; then
      echo "IPv6 address unchanged"
      exit
    fi

    mailtxt=$HOME/.mail.$name
    sdate=`date +%Y年%m月%d日%t%H:%M:%S`

    #写好邮件
    cat > $mailtxt <<EOF
    From:${fromaddress}
    To:${toaddress}
    Subject:IP发生变更,打开查看详情
    系统于 ${sdate} 检测到设备:${name} 的IP已发生变更!
    新的IP为  ${ipaddress}
    EOF

    #发送邮件
    sendmail -f $fromaddress -t $toaddress -S $smtpserver -au$fromaddress -ap$fromaddresspwd < $mailtxt

    #缓存当前ip地址到文件
    echo $ipaddress > $file

    #打印系统日志
    logger 监测到设备 $name 的IPv6变更,已邮件通知 $toaddress
  2. ssh连接到路由器,添加mailuip,sh的可执行权限,保存之前的计划任务
    1
    2
    3
    cd /etc/storage
    chmod +x mailuip.sh
    crontab -l > mailcron
  3. 添加需要发送 ip 的设备,每 10 分钟自动执行一次检查。注意!设备名自定但必须是英文否则会出错,MAC 地址要求按照带有冒号分隔符的格式,例如xx:xx:xx:xx:xx:xx
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #参数格式说明:./mailuip.sh [模式] [设备名] [MAC地址]
    cat >> mailcron <<EOF
    #添加路由器
    */10 * * * * /etc/storage/mailuip.sh router
    #添加下级设备
    #可以添加多个设备,每一行对应一个设备
    */10 * * * * /etc/storage/mailuip.sh neigh 设备名 MAC地址
    # ......
    EOF
    #对于下级设备举例如下,注意空格不能丢
    #*/10 * * * * /etc/storage/mailuip.sh neigh iphone 11:22:33:aa:bb:cc
    #*/10 * * * * /etc/storage/mailuip.sh neigh mypc ee:ff:gg:11:22:33
  4. 启动计划任务
    1
    crontab mailcron
  5. 在 Padavan 的后台管理页找到高级设置->自定义设置->脚本->在 WAN 上行/下行启动后执行中添加以下命令,就可以在重启路由后立即发送最新 IP 地址。
    1
    2
    3
    4
    #对于路由器
    /etc/storage/mailuip.sh router
    #或者是下级设备
    /etc/storage/mailuip.sh neigh 设备名 MAC地址

    END

    记一下编辑脚本时遇到的问题

    在 windows 下的换行与 Linux 的换行不同,互不兼容,这就导致在 windows 记事本中编辑过的 shell 脚本,放在 Linux 下无法运行。最后处理方法是用 VS Code 打开,点击右下角CRLF,选择行尾序列,改为LF保存即可。

参考

家用宽带的 IPv6 配置: https://lwz322.github.io/2019/07/25/IPv6_Home.html

V2EX › 宽带症候群 如何远程找到家里设备的 IPV6 地址?: https://www.v2ex.com/t/592571

知乎-IPV6 网络下建立安全的家庭服务器[NAS]: https://zhuanlan.zhihu.com/p/75247811

老毛子华硕 Padavan 外网 IP 变化自动发送邮件脚本 Padavan 添加 shell 脚本: https://aisoa.cn/post-2506.html

dynv6.com official update script: https://gist.github.com/corny/7a07f5ac901844bd20c9

V2EX › 宽带症候群 家庭宽带 私设 web 被检测 魔都电信被停宽带: https://v2ex.com/t/608821?p=1

V2EX › 宽带症候群 应对家宽 Web 的收紧,讨论一下在外网控制家庭设备的方案: https://v2ex.com/t/635028#reply63