美文网首页
软路由折腾之路

软路由折腾之路

作者: 一个大大大坑 | 来源:发表于2020-04-08 00:27 被阅读0次

Setup Software Router

最近想设置一个自己的服务器,一方面合理利用宽带的公网IP资源,可以在服务器上运行一些常规的服务,一方面能够替换掉TPlink路由器,作为一个家庭网关。遂规划搭建一个软路由。

规划

当前服务器有两个有线网卡,eno1enp2s0,一个wifi网卡 wlp3s0

将 eno1 作为 WAN 口进行pppoe与服务商连接,enp2s0 作为有线 LAN 口对内网提供服务。wlp3s0 提供2.4G/5G wifi 作为WLAN使用。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 70:85:c2:a9:d5:02 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::7285:c2ff:fea9:d502/64 scope link 
       valid_lft forever preferred_lft forever
3: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 70:85:c2:a9:d5:00 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::7285:c2ff:fea9:d500/64 scope link 
       valid_lft forever preferred_lft forever
4: wlp3s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 3c:6a:a7:a0:d6:10 brd ff:ff:ff:ff:ff:ff

netplan setup

ubuntu server 默认使用 systemd-network 配合 netplan 进行网络管理。自身非常精简,仅提供了常用的功能。

此外 cloud-init 也是使用的 netplan 的配置格式进行配置的,所以先研究了一下 netplan 相关。

先看官方文档:netplan reference

还可以看示例配置:netplan examples

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 70:85:c2:a9:d5:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.101.6/24 brd 192.168.101.255 scope global enp2s0
       valid_lft forever preferred_lft forever
    inet6 fe80::7285:c2ff:fea9:d502/64 scope link 
       valid_lft forever preferred_lft forever
3: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 70:85:c2:a9:d5:00 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.5/24 brd 192.168.1.255 scope global dynamic eno1
       valid_lft 86231sec preferred_lft 86231sec
    inet6 fe80::7285:c2ff:fea9:d500/64 scope link 
       valid_lft forever preferred_lft forever
4: wlp3s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 3c:6a:a7:a0:d6:10 brd ff:ff:ff:ff:ff:ff

/etc/netplan/interfaces.yaml

network:
  version: 2
  ethernets:
    enp2s0: 
      dhcp4: true
    eno1:
      dhcp4: true

pppoe setup

netplan 不支持设置 pppoe,因 networkd 也不支持设置 pppoe 。
参见add pppoe support to systemd-networkd·Issue481,因networkd认为pppoe作为"老旧"的技术,且不再云环境中常用,所以在其路标上不计划该特性。(我觉得有道理,能够坚持在cloud方向做好)

转而使用 ppp 进行pppoe配置。推荐配合 networkd-dispatcher 使用,该组件是类似于 ifupdown 的hook,也提供了存放hook脚本的地方。

推荐查看官方文档: networkd-dispatcher

决定在 /etc/networkd-dispatcher/carrier.d 中编写脚本,在eno1端口负载时进行pppoe连接。

安装 ppp

sudo apt-get install ppp

推荐查看官方文档: PPP github或者gitweb on ozlabs.org或者 man pppd 以了解如何使用。其中官方文档对 pppoe 提供了详细说明 README.pppoe

编写 pppoe config /etc/ppp/peers/eno1

plugin rp-pppoe.so nic-eno1
ifname ppp0
user "CDXXXXXXXX"
noipdefault
usepeerdns
defaultroute
persist
noauth
+ipv6 ipv6cp-use-ipaddr

配置 pap-secrets /etc/ppp/pap-secrets,为了某种安全考虑,ppp将密码文件与配置文件分开存放,使用时会根据配置中的 username 在 secrets 中寻找对应的密码进行使用。

sudo sh -c 'echo "CDXXXXXXXX * XXXXXXXX" >> /etc/ppp/pap-secrets'

编写 hook script /etc/networkd-dispatcher/carrier.d/setup-pppoe.sh

#!/bin/env sh

# interface to pppoe workload
INTERFACE=eno1

if [ "${IFACE}" = "${INTERFACE}" ] ; then
    echo "running pon ${INTERFACE}..."
    pon ${INTERFACE}
fi

pon 命令由 ppp 提供,其本质是一个shell script,感兴趣的可以 cat $(which pon)看一下内容

ddns setup

pppoe 由于是家用的,每次获取到的公网地址随机,因此需要使用ddns来动态解析以获取我们真实的地址。以后服务器的服务可以基于该dns进行使用。

ddns 使用的是多年前的 dnspod 服务(现已经被腾讯云收购,不过还可以正常使用),Dnspod API文档

创建 hook script /etc/networkd-dispatcher/routable.d/setup-ddns.sh,也可在我的github上etc/openwrt查看该script内容。

#!/bin/sh

INTERFACE=ppp0  #networkd-dispacher IFACE - interface that triggered the event

LOGIN_TOKEN="ID,TOKEN"
DOMAIN="<DOMAIN>"
SUB_DOMAIN="<SUB_DOMAIN>"

DNSPOD_HOST=https://dnsapi.cn
RECORED_LIST_PATH=Record.List
RECORED_UPDATE_PATH=Record.Modify

getRecord(){
    curl -s -X POST -d "login_token=${LOGIN_TOKEN}&format=json&domain=${DOMAIN}" ${DNSPOD_HOST}/${RECORED_LIST_PATH} | jq '.records[]|select(.name=="'${SUB_DOMAIN}'" and .type=="A")'
}

updateRecord(){
    curl -s -X POST -d "login_token=${LOGIN_TOKEN}&format=json&domain=${DOMAIN}&sub_domain=${SUB_DOMAIN}&record_id=${1}&record_type=A&record_line_id=0&value=${2}" ${DNSPOD_HOST}/${RECORED_UPDATE_PATH}
}

record=$(getRecord)
externalIP=$ADDR  #networkd-dispacher ADDR - the ipv4 address of the device

if [ "${IFACE}" != "${INTERFACE}" ] ; then
  echo "skip event ${STATE} ${IFACE} ${ADDR}"
  exit
fi 

if [ "$(echo "$record"|jq -r '.value')" != "$externalIP" ] ; then
    echo "dns record value [$(echo "$record" | jq -r .value )] is out of date, updating to [$externalIP]"
    updateRecord "$(echo "$record"|jq -r .id)" "${externalIP}"
    else
    echo "dns record value [$(echo "$record" | jq -r .value )] is up to date, nothing todo"
fi

相关文章

网友评论

      本文标题:软路由折腾之路

      本文链接:https://www.haomeiwen.com/subject/rhiaphtx.html