本文使用“署名-非商业性使用-相同方式共享 4.0 国际(CC BY-NC-SA 4.0)”进行许可。
商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接。 如果您再混合、转换或者基于本作品进行创作,您必须基于相同的协议分发您贡献的作品。
虽然 PPPoE - Debian Wiki 给的还是用 pppoeconf
这个包来配置,但是其实它最近一次功能性更新是在 2014 年(Commits · master · Debian / pppoeconf · GitLab),不过也还能用。
开始动手前,可以去 ppp - ArchWiki 看一看,arch 的 wiki 确实详细,虽然他里面提到的 pppoeconfig
和 开机自启的方法在 Debian 上时用不了的,但是可以了解一下 ppp 包的配置文件分别代表什么。
pppoeconf
配置如果彻底没网装不了
pppoeconf
,可以按照上面给的 arch wiki 手动拨号(也要同时参考本文下方的“具体更改”节)。
sudo apt install pppoeconf
,之后直接输入 pppoeconf
然后回车,除了要输入的全部保持默认选择,输入 username 时要把他给的 username
这个占位符删了。(如果有多个网卡,在第一步会让选择)
启动 pon dsl-provider
停止 poff
Warning
由于未知原因,请不要使用 NetworkManager 的 nmcli
或者 nmtui
管理你的网络——这样 outbound 没问题,但是 inbound 会连不上。
首先,它在 /etc/ppp/peers
中新建了一个 dsl-provider
文件,这个文件夹中每个文件都是一个连接配置,文件名是连接名称。自动生成的应该如下
# Minimalistic default options file for DSL/PPPoE connections
noipdefault
defaultroute
replacedefaultroute
hide-password
#lcp-echo-interval 30
#lcp-echo-failure 4
noauth
persist
#mtu 1492
#persist
#maxfail 0
#holdoff 20
plugin rp-pppoe.so
nic-enp1s0
user "your_username"
usepeerdns
密码保存在 /etc/ppp/pap-secrets
和 /etc/ppp/chap-secrets
文件中。
通过 ppp 获取的 nameserver 会存储在 /etc/ppp/resolv.conf
中。
接着看 /etc/network/interfaces
,多出了以下内容:
auto dsl-provider
iface dsl-provider inet ppp
pre-up /bin/ip link set enp1s0 up # line maintained by pppoeconf
provider dsl-provider
auto enp1s0
iface enp1s0 inet manual
按照 Ubuntu Manpage: /etc/network/interfaces 说法,上面四行等价于 pon dsl-provider
,并且将它与 enp1s0
网卡关联,下面就是 auto 设置 enp1s0
网卡了。这样相当于可以开机启动 PPPoE 连接。
如果开机 ifconfig
没看到 ppp0 网卡,稍等片刻或者 journalctl -b --grep=pppd
看看——拨号也是需要时间的。
如果你的 dsl 服务商不稳定,需要经常重启 ppp 服务,那么这段内容可能对你有用。一般来说,poff
之后再 pon
的话,网口名 ppp0
会变成 ppp1
,依次递增,如果你有脚本依赖于 ppp0
或者对 ppp0
做了 ddns,或许想要固定这一名称。
参考:
https://unix.stackexchange.com/questions/145692/naming-ppp-interfaces
简单来讲,就是在 /etc/ppp/peers/dsl-provider
中新增一行 ifname 名字
即可(可能不是对所有发行版生效,至少本文探讨的 Debian 和大多数应该都可以)。
因此,最终我的配置是这样的, ifname 选用的是 pppdsl
:
# Minimalistic default options file for DSL/PPPoE connections
noipdefault
defaultroute
replacedefaultroute
hide-password
#lcp-echo-interval 30
#lcp-echo-failure 4
noauth
persist
#mtu 1492
#persist
#maxfail 0
#holdoff 20
plugin rp-pppoe.so
nic-enp1s0
user "thePlaceholderUsername"
usepeerdns
ifname pppdsl
在 Debian 上(Debian12.2)一个卡住了我很久的事情就是在 /etc/ppp
中给了 ip-up.d
等文件夹,但实际上并没有人去调用这些文件夹中的脚本!pppd 调用的时 ip-up
等脚本,需要 ip-up
自己去 run-parts
那些.d 文件夹中的脚本。我不清楚其他发行版时如何的,但是如果你发现自己的 /etc/ppp/
下没有 ip-up
等脚本,请自己新建一个,并且一定要有 #!
开头。
比如可以在 ip-up
将 ppp 获得的 nameserver 写入到系统中(需要配置文件中包含 userpeerdns
):
#!/bin/sh
if [ "$USEPEERDNS" = "1" -a -f /etc/ppp/resolv.conf ]; then
[ -e /etc/resolv.conf ] && mv /etc/resolv.conf /etc/resolv.conf.backup.${IFNAME}
mv /etc/ppp/resolv.conf /etc/resolv.conf
chmod 644 /etc/resolv.conf
fi
copied from https://github.com/mdlawson/hoth-server/blob/master/etc/ppp/ip-up.d/00-dns.sh
由于这是一台无公网 IP 的虚拟机,它拨号上的网是我唯一从网络上访问它的办法,因此,我需要一些办法获取它每次重新拨号之后获得的 IPv4 和 IPv6 地址。一个办法就是使用 ip-up
脚本,另一个则是用 DDNS。本文着重介绍一下 ip-up
脚本的办法,在拨号成功后,用 ip
命令获取地址,然后通过 Bark 推送给自己。
LLM 帮我写了这两条:
ip -4 addr show dev pppdsl | grep inet | awk '{print $2}' | cut -d/ -f1 # 获取IPv4 地址
ip -6 addr show dev pppdsl | grep inet6 | grep -v ' scope link ' | awk '{print $2}' | cut -d/ -f1 # 获取 IPv6 地址,并且不会返回本地地址
其中 pppdsl
是前面 固定 interface 名称 中使用的 ifname
。
Tip
如果你选择的安装镜像过于干净而没有 ip
命令,请安装 iproute2
包。
下面是我用的 /etc/ppp/ip-up
和 /etc/ppp/ipv6-up
内容。
首先它会用上面提到的命令获取 IP,然后发起一个请求给 Bark 的服务器来给我的手机推送通知。
需要注意的点:
stdout
和在文件中设定的 LOG_FILE
变量的文件中输出日志。urlencode()
函数就是干这事的。ipv6-up
被调用,所以我在 ipv6-up
中等待了 10 秒才开始获取地址。#!/bin/bash
# /etc/ppp/ip-up
# https://yfi.moe/post/debian-pppoe
/etc/ppp/ip-up.d/00-dns
urlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
LOG_FILE="/root/ppp-up4.log"
log() {
local message="$1" # 要打印的消息
# 打印到stdout
echo -e "$message"
# 写入日志文件
echo -e "$message" >> "$LOG_FILE"
}
current_time=$(date "+%Y-%m-%d %H:%M:%S")
log "============= IPv4 @ $current_time ==============="
IPADDR=`ip -4 addr show dev pppdsl | grep inet | awk '{print $2}' | cut -d/ -f1`
if [ -n "$IPADDR" ]; then
log "IPv4: $IPADDR"
IPADDR_ENC=$(urlencode "$IPADDR")
URL="https://api.day.app/doUX9Cx9QBnYbD9hPKEX9J/ANA-PPP-IPv4/$IPADDR_ENC"
curl -s "$URL" | tee -a $LOG_FILE
log ""
else
log "NO IPv4 addr found"
fi
log "********************************************************\n"
#!/bin/bash
# /etc/ppp/ipv6-up
# https://yfi.moe/post/debian-pppoe
LOG_FILE="/root/ppp-up6.log"
urlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
log() {
local message="$1" # 要打印的消息
# 打印到stdout
echo -e "$message"
# 写入日志文件
echo -e "$message" >> "$LOG_FILE"
}
current_time=$(date "+%Y-%m-%d %H:%M:%S")
sleep 10 # 一开始只能拿到内网ipv6,应该是外网的ipv6还没下发下来,所以先等10s
log "============= IPv6 @ $current_time ==============="
IPADDR=`ip -6 addr show dev pppdsl | grep inet6 | grep -v ' scope link ' | awk '{print $2}' | cut -d/ -f1`
if [ -n "$IPADDR" ]; then
log "IPv6: $IPADDR"
IPADDR_ENC=$(urlencode "$IPADDR")
URL="https://api.day.app/doUX9Cx9QBnYbD9hPKEX9J/ANA-PPP-IPv6/$IPADDR_ENC"
curl -s "$URL" | tee -a $LOG_FILE
log ""
else
log "NO IPv6 addr found"
ip a >> $LOG_FILE
URL="https://api.day.app/THEKEYOFYOURDEVICE/ANA-PPP-IPv6/NO-IPv6-addr-found"
curl -s "$URL"
fi
log "********************************************************\n"
别忘了 chmod
添加执行权限哦!
可以直接执行脚本看看输出,也可以 pon
/ poff
一下试试。
本文使用“署名-非商业性使用-相同方式共享 4.0 国际(CC BY-NC-SA 4.0)”进行许可。
商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接。 如果您再混合、转换或者基于本作品进行创作,您必须基于相同的协议分发您贡献的作品。