首页
iYoRoy DN42 Network
关于
友情链接
Language
简体中文
English
Search
1
Docker下中心化部署EasyTier
2,241 阅读
2
给Android 4.9内核添加KernelSU支持
1,340 阅读
3
在TrueNAS上使用Docker安装1Panel
379 阅读
4
记一次为Android 4.9内核的ROM启用erofs支持
370 阅读
5
2025羊城杯初赛WriteUp
365 阅读
Android
运维
NAS
开发
网络技术
专题向研究
DN42
个人ISP
CTF
网络安全
登录
Search
标签搜索
网络技术
BGP
Linux
BIRD
DN42
C&C++
Android
Windows
OSPF
Docker
AOSP
MSVC
服务
DNS
STL
内部路由协议
Kernel
caf/clo
Web
TrueNAS
神楽悠笙
累计撰写
28
篇文章
累计收到
14
条评论
首页
栏目
Android
运维
NAS
开发
网络技术
专题向研究
DN42
个人ISP
CTF
网络安全
页面
iYoRoy DN42 Network
关于
友情链接
Language
简体中文
English
搜索到
9
篇与
的结果
记一次手动安装Proxmox VE, 配置多路iSCSI与NAT转发的经历
起因是租了一台物理机, 然后IDC那边没有提供PVE和Debian系统镜像, 只有Ubuntu、CentOS、Windows系列. 同时数据盘是通过多路iSCSI提供的. 我希望使用PVE来对不同使用场景进行隔离, 因此尝试重装并迁移上述配置. 备份配置 首先对系统做个大致的检查, 可发现: 系统存在两张网卡, 一张enp24s0f0接入了公网地址, 用于外部访问; 一张enp24s0f1接入了192.168.128.153的私网地址 数据盘被映射为了/dev/mapper/mpatha /etc/iscsi下存在两个iSCSI Node的配置, 分别为192.168.128.250:3260、192.168.128.252:3260, 但是二者都对应iqn.2024-12.com.ceph:iscsi. 不难推断出, 数据盘挂载是通过同时配置两个iSCSI Node, 再使用多路的方式合并成一个设备. 查看一下系统的网络配置: network: version: 2 renderer: networkd ethernets: enp24s0f0: addresses: [211.154.[数据删除]/24] routes: - to: default via: [数据删除] match: macaddress: ac:1f:6b:0b:e2:d4 set-name: enp24s0f0 nameservers: addresses: - 114.114.114.114 - 8.8.8.8 enp24s0f1: addresses: - 192.168.128.153/17 match: macaddress: ac:1f:6b:0b:e2:d5 set-name: enp24s0f1 发现就是非常简单的静态路由, 内网网卡甚至没有默认路由, 直接绑定IP即可. 然后将/etc/iscsi下iSCSI的配置文件保存一下, 其中包含了账户密码等信息 重装Debian 此次使用的是bin456789/reinstall重装脚本. 下载脚本: curl -O https://cnb.cool/bin456789/reinstall/-/git/raw/main/reinstall.sh || wget -O ${_##*/} $_ 重装成Debian 13: bash reinstall.sh debian 13 然后根据提示输入你想要设置的密码即可 如果不出意外的话, 等待10分钟左右, 会自动完成并重装成一个纯净的Debian 13. 中途可以通过ssh配合设置的密码连接, 查看安装进度. 重装完成后按照惯例进行一个换源和apt upgrade, 即可得到一个纯净的Debian 13啦 换源直接参考USTC镜像站的教程即可 安装Proxmox VE 这一步主要参考Proxmox官方的教程即可 需要注意,上述脚本安装的Debian会将主机名设置为localhost,你如果想要修改的话请在配置Hostname前修改并将hosts中的主机名改成你修改的主机名而非localhost 配置Hostname Proxmox VE要求为当前的主机名配置一个指向非回环地址的Hosts: The hostname of your machine must be resolvable to an IP address. This IP address must not be a loopback one like 127.0.0.1 but one that you and other hosts can connect to. 比如此处我的服务器IP为211.154.[数据删除], 我需要在/etc/hosts中添加如下的一条记录: 127.0.0.1 localhost +211.154.[数据删除] localhost ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters 保存后, 使用hostname --ip-address检查是否会输出设置的非回环地址: ::1 127.0.0.1 211.154.[数据删除] 添加Proxmox VE软件源 Debian 13使用了Deb822格式当然你想用sources.list也可以, 因此直接参考USTC的Proxmox镜像站即可: cat > /etc/apt/sources.list.d/pve-no-subscription.sources <<EOF Types: deb URIs: https://mirrors.ustc.edu.cn/proxmox/debian/pve Suites: trixie Components: pve-no-subscription Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg EOF 此处需要同步迁移一个keyring过来但是我上网找了一圈没找到, 因此我选择从我现有的一个Proxmox VE服务器上拉过来一份. 放在这里了: proxmox-keyrings.zip 将公钥文件解压放在/usr/share/keyrings/中, 然后运行 apt update apt upgrade -y 即可同步Proxmox VE软件源 安装Proxmox VE内核 使用如下命令安装PVE内核并重启以应用新内核: apt install proxmox-default-kernel reboot 之后通过uname -r应该能看到当前使用的是类似于6.17.2-2-pve这样以pve结尾的内核版本, 代表新内核应用成功. 安装Proxmox VE相关软件包 使用apt安装对应软件包: apt install proxmox-ve postfix open-iscsi chrony 配置过程中会需要设置postfix邮件服务器, 官方解释: 如果您的网络中有邮件服务器, 则应将postfix配置为Satellite system. 然后, 您现有的邮件服务器将成为中继主机, 将Proxmox VE发送的电子邮件路由到其最终收件人. 如果您不知道在此处输入什么, 请仅选择Local only, 并保持系统hostname不变. 之后应该能访问https://<你的服务器地址>:8006来打开Web控制台了, 账户为root, 密码为你的root密码, 即重装Debian时配置的密码. 删除旧的Debian内核和os-prober 使用以下命令: apt remove linux-image-amd64 'linux-image-6.1*' update-grub apt remove os-prober 来移除旧的Debian内核, 更新grub并移除os-prober. 移除os-prober不是必须的, 但是官方建议这么做, 因为它可能会误将虚拟机的引导文件认成多系统的引导文件, 导致将不该加的一些东西加到引导列表中. 至此, Proxmox VE的安装就完成了, 已经可以正常使用啦! 配置内网网卡 因为IDC那边iSCSI网卡和公网走的不是同一张, 而重装的时候丢失了这部分的配置, 因此需要手动配置一下内网的网卡. 打开Proxmox VE的Web后台, 找到Datacenter-localhost(主机名)-Network, 编辑内网网卡, 如我这里的是ens6f1, 填入上面备份的IPv4的CIDR格式: 192.168.128.153/17并勾选Autostart, 接着保存即可. 接着使用命令来设置网卡状态为UP: ip link set ens6f1 up 现在能Ping通内网iSCSI服务器的IP了. 配置数据盘 iSCSI 在上一步中, 我们应该已经安装了iscsiadm所需的软件包open-iscsi, 我们只需要按照之前备份的配置重新设置node即可. 首先发现一下iSCSI存储: iscsiadm -m discovery -t st -p 192.168.128.250:3260 可以得到原先存在的两个LUN Target: 192.168.128.250:3260,1 iqn.2024-12.com.ceph:iscsi 192.168.128.252:3260,2 iqn.2024-12.com.ceph:iscsi 将备份的配置文件传到服务器上, 覆盖掉原先的/etc/iscsi中的配置, 同时, 在我备份的配置中可以找到验证方面的配置: # /etc/iscsi/nodes/iqn.2024-12.com.ceph:iscsi/192.168.128.250,3260,1/default # BEGIN RECORD 2.1.5 node.name = iqn.2024-12.com.ceph:iscsi ... # 略去一些不重要的配置 node.session.auth.authmethod = CHAP node.session.auth.username = [数据删除] node.session.auth.password = [数据删除] node.session.auth.chap_algs = MD5 ... # 略去一些不重要的配置 # /etc/iscsi/nodes/iqn.2024-12.com.ceph:iscsi/192.168.128.252,3260,2/default # BEGIN RECORD 2.1.5 node.name = iqn.2024-12.com.ceph:iscsi ... # 略去一些不重要的配置 node.session.auth.authmethod = CHAP node.session.auth.username = [数据删除] node.session.auth.password = [数据删除] node.session.auth.chap_algs = MD5 ... # 略去一些不重要的配置 按照这些配置文件写入新的系统: iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 -o update -n node.session.auth.authmethod -v CHAP iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 -o update -n node.session.auth.username -v [数据删除] iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 -o update -n node.session.auth.password -v [数据删除] iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 -o update -n node.session.auth.chap_algs -v MD5 iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.252:3260 -o update -n node.session.auth.authmethod -v CHAP iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.252:3260 -o update -n node.session.auth.username -v [数据删除] iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.252:3260 -o update -n node.session.auth.password -v [数据删除] iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 -o update -n node.session.auth.chap_algs -v MD5 (我不知道为什么验证信息需要单独写入一次, 但是实测下来不重写它无法登录) 接着, 使用: iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 --login iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.252:3260 --login 登录Target, 接着使用: iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.250:3260 -o update -n node.startup -v automatic iscsiadm -m node -T iqn.2024-12.com.ceph:iscsi -p 192.168.128.252:3260 -o update -n node.startup -v automatic 开启开机自动挂载. 这个时候通过lsblk之类的工具查看磁盘应该就能发现多了两块硬盘, 我这里多出来了sdb和sdc. 配置multipath多路径 关于如何识别出是多路径设备, 我尝试通过: /usr/lib/udev/scsi_id --whitelisted --device=/dev/sdb /usr/lib/udev/scsi_id --whitelisted --device=/dev/sdc 查看两个磁盘设备的scsi_id, 发现二者是相同的, 因此可推断二者是同一块盘, 使用了多路来实现类似负载均衡和故障转移的效果 使用apt安装multipath: apt install multipath-tools 接着, 创建/etc/multipath.conf并填入: defaults { user_friendly_names yes find_multipaths yes } 配置multipathd开机自启: systemctl start multipathd systemctl enable multipathd 接着, 使用如下指令扫描并自动配置多路设备: multipath -ll 会输出: mpatha(360014056229953ef442476e85501bfd7)dm-0LIO-ORG,TCMU device size=500G features='1 queue_if_no_path' hwhandler='1 alua'wp=rw |-+- policy='service-time 0' prio=50 status=active | `- 14:0:0:152 sdb 8:16 active ready running `-+- policy='service-time 0' prio=50 status=active `- 14:0:0:152 sdc 8:16 active ready running 可看到已经将两块盘识别成同一个多路设备了. 此时, 可以在/dev/mapper/下找到多路设备的磁盘: root@localhost:/dev/mapper# ls control mpatha mpatha即为多路聚合的磁盘. 如果没扫描到,可尝试使用: rescan-scsi-bus.sh 重新扫描SCSI总线后再次尝试,若提示找不到这个指令可以用apt install sg3-utils安装. 实在不行咱重启一下 配置Proxmox VE使用数据盘 因为我们使用了多路, 因此不能直接选择添加iSCSI类型的存储. 使用如下指令创建PV和VG: pvcreate /dev/mapper/mpatha vgcreate <vg名称> /dev/mapper/mpatha 此处我将整块盘都配置成了PV, 你也可以单独划分出来一个分区来做这件事 完成后, 打开Proxmox VE的后台管理, 找到Datacenter-Storage, 点击Add-LVM, Volume group选择刚刚创建的VG的名称, ID自己给他命个名, 然后点击Add即可. 自此, 所有原系统的配置应该已经都迁移过来了 配置NAT NAT地址转换 因为只买了一个IPv4地址, 所以需要配置一下NAT来让所有虚拟机都能正常上网. 打开/etc/network/interfaces, 添加如下内容: auto vmbr0 iface vmbr0 inet static address 192.168.100.1 netmask 255.255.255.0 bridge_ports none bridge_stp off bridge_fd 0 post-up echo 1 > /proc/sys/net/ipv4/ip_forward post-up iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o ens6f0 -j MASQUERADE post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1 post-up iptables -A FORWARD -i vmbr0 -j ACCEPT post-down iptables -t nat -D POSTROUTING -s 192.168.100.0/24 -o ens6f0 -j MASQUERADE post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1 post-down iptables -D FORWARD -i vmbr0 -j ACCEPT 其中, vmbr0为NAT网桥, 网桥IP段为192.168.100.0/24 , 该网段流量会被转换为ens6f0外网网卡的IP发出, 并在收到回复时转换为原始IP, 实现共享外部IP. 接着, 使用: ifreload -a 重载配置. 到此, 虚拟机就已经能实现上网了, 只需要安装的时候配置静态地址为192.168.100.0/24内的地址, 默认网关设置为192.168.100.1, 并配置DNS地址即可. 端口转发 懒了, 直接拷打AI 让AI写了个配置脚本/usr/local/bin/natmgr: #!/bin/bash # =================配置区域================= # 公网网卡名称 (请根据实际情况修改) PUB_IF="ens6f0" # ========================================= ACTION=$1 ARG1=$2 ARG2=$3 ARG3=$4 ARG4=$5 # 检查是否为 root 用户 if [ "$EUID" -ne 0 ]; then echo "请使用 root 权限运行此脚本" exit 1 fi # 生成随机 ID (6位字符) generate_id() { # 引入纳秒和随机盐以确保即使脚本执行速度很快,ID也不会重复 echo "$RANDOM $(date +%s%N)" | md5sum | head -c 6 } # 显示帮助信息 usage() { echo "用法: $0 {add|del|list|save} [参数]" echo "" echo "命令:" echo " add <公网端口> <内网IP> <内网端口> [协议] 添加转发规则" echo " [协议] 可选: tcp, udp, both (默认: both)" echo " del <ID> 通过 ID 删除转发规则" echo " list 查看当前所有转发规则" echo " save 保存当前规则,使其在重启后仍然存在 (必须运行!)" echo "" echo "示例:" echo " $0 add 8080 192.168.100.101 80 both" echo " $0 save" echo "" } # 内部函数:添加单条协议规则 _add_single_rule() { local PROTO=$1 local L_PORT=$2 local T_IP=$3 local T_PORT=$4 local RULE_ID=$(generate_id) local COMMENT="NAT_ID:${RULE_ID}" # 1. 添加 DNAT 规则 (PREROUTING 链) iptables -t nat -A PREROUTING -i $PUB_IF -p $PROTO --dport $L_PORT -j DNAT --to-destination $T_IP:$T_PORT -m comment --comment "$COMMENT" # 2. 添加 FORWARD 规则 (允许数据包通过) iptables -A FORWARD -p $PROTO -d $T_IP --dport $T_PORT -m comment --comment "$COMMENT" -j ACCEPT # 输出结果 printf "%-10s %-10s %-10s %-20s %-10s\n" "$RULE_ID" "$PROTO" "$L_PORT" "$T_IP:$T_PORT" "成功" # 提醒用户保存 echo "请运行 '$0 save' 命令以确保规则在重启后仍然存在。" } # 主添加函数 add_rule() { local L_PORT=$1 local T_IP=$2 local T_PORT=$3 local PROTO_REQ=${4:-both} # 默认为 both if [[ -z "$L_PORT" || -z "$T_IP" || -z "$T_PORT" ]]; then echo "错误: 参数缺失" usage exit 1 fi # 转换为小写 PROTO_REQ=$(echo "$PROTO_REQ" | tr '[:upper:]' '[:lower:]') echo "正在添加规则..." printf "%-10s %-10s %-10s %-20s %-10s\n" "ID" "协议" "公网端口" "目标地址" "状态" echo "------------------------------------------------------------------" if [[ "$PROTO_REQ" == "tcp" ]]; then _add_single_rule "tcp" "$L_PORT" "$T_IP" "$T_PORT" elif [[ "$PROTO_REQ" == "udp" ]]; then _add_single_rule "udp" "$L_PORT" "$T_IP" "$T_PORT" elif [[ "$PROTO_REQ" == "both" ]]; then _add_single_rule "tcp" "$L_PORT" "$T_IP" "$T_PORT" _add_single_rule "udp" "$L_PORT" "$T_IP" "$T_PORT" else echo "错误: 不支持的协议 '$PROTO_REQ'。请使用 tcp, udp 或 both。" exit 1 fi echo "------------------------------------------------------------------" } # 删除规则 (基于行号倒序删除) del_rule() { local RULE_ID=$1 if [[ -z "$RULE_ID" ]]; then echo "错误: 请提供规则 ID" usage exit 1 fi echo "正在搜索 ID 为 [${RULE_ID}] 的规则..." local FOUND=0 # --- 清理 NAT 表 (PREROUTING) --- LINES=$(iptables -t nat -nL PREROUTING --line-numbers | grep "NAT_ID:${RULE_ID}" | awk '{print $1}' | sort -rn) if [[ ! -z "$LINES" ]]; then for line in $LINES; do iptables -t nat -D PREROUTING $line echo "已删除 NAT 表 PREROUTING 链第 $line 行" FOUND=1 done fi # --- 清理 Filter 表 (FORWARD) --- LINES=$(iptables -t filter -nL FORWARD --line-numbers | grep "NAT_ID:${RULE_ID}" | awk '{print $1}' | sort -rn) if [[ ! -z "$LINES" ]]; then for line in $LINES; do iptables -t filter -D FORWARD $line echo "已删除 Filter 表 FORWARD 链第 $line 行" FOUND=1 done fi if [[ $FOUND -eq 0 ]]; then echo "未找到 ID 为 $RULE_ID 的规则。" else echo "删除操作完成。" echo "请运行 '$0 save' 命令以更新持久化配置文件。" fi } # 保存规则到磁盘 (新增功能) save_rules() { echo "正在保存当前的 iptables 规则..." # netfilter-persistent 是 Debian/Proxmox 中管理 iptables-persistent 的服务 if command -v netfilter-persistent &> /dev/null; then netfilter-persistent save if [ $? -eq 0 ]; then echo "✅ 规则已成功保存到 /etc/iptables/rules.v4,将在系统重启后自动恢复。" else echo "❌ 规则保存失败。请检查 'netfilter-persistent' 服务状态。" fi else echo "警告: 未找到 'netfilter-persistent' 命令。" echo "请确保已安装 'iptables-persistent' 软件包。" echo "安装命令: apt update && apt install iptables-persistent" fi } # 列出规则 list_rules() { echo "当前端口转发规则列表:" printf "%-10s %-10s %-10s %-20s %-10s\n" "ID" "协议" "公网端口" "目标地址" "目标端口" echo "------------------------------------------------------------------" # 解析 iptables 输出 iptables -t nat -nL PREROUTING -v | grep "NAT_ID:" | while read line; do id=$(echo "$line" | grep -oP '(?<=NAT_ID:)[^ ]*') # 提取协议 if echo "$line" | grep -q "tcp"; then proto="tcp"; else proto="udp"; fi # 提取 dpt: 之后的端口 l_port=$(echo "$line" | grep -oP '(?<=dpt:)[0-9]+') # 提取 to: 之后的 IP:Port target=$(echo "$line" | grep -oP '(?<=to:).*') t_ip=${target%:*} t_port=${target#*:} printf "%-10s %-10s %-10s %-20s %-10s\n" "$id" "$proto" "$l_port" "$t_ip" "$t_port" done } # 主逻辑 case "$ACTION" in add) add_rule "$ARG1" "$ARG2" "$ARG3" "$ARG4" ;; del) del_rule "$ARG1" ;; list) list_rules exit 0 ;; save) save_rules ;; *) usage exit 1 ;; esac save_rules 让其自动添加/删除iptables规则实现端口转发. 记得chmod +x 通过iptables-persistent实现保存配置开机自动加载: apt install iptables-persistent 配置过程中会询问是否需要保存当前规则,Yes或者No都可以。 添加转发规则时使用natmgr add <主机监听地址> <虚拟机内网IP> <虚拟机端口> [tcp/udp/both]即可, 脚本会自动分配一个唯一ID, 删除时使用natmgr del <ID>即可. 也可使用natmgr list查看已有转发列表. 参考文章: bin456789/reinstall: 一键DD/重装脚本 (One-click reinstall OS on VPS) - GitHub Install Proxmox VE on Debian 12 Bookworm - Proxmox VE PVE连接 TrueNAS iSCSI存储实现本地无盘化_pve iscsi-CSDN博客 ProxmoxVE (PVE) NAT 网络配置方法 - Oskyla 烹茶室
2025年11月29日
115 阅读
0 评论
0 点赞
DN42&OneManISP - 使用VRF实现公网BGP和DN42共用一台机器
背景 目前同一区域内公网BGP和DN42分别用了一台VPS,也就是说同一个区域需要两台机器。从群友那里得知了VRF,便想着通过VRF实现同一台机器同时处理公网BGP并加入DN42。 注意:VRF方案因为其隔离性,会导致DN42无法访问主机的服务。如果你需要在服务器上跑诸如DNS之类的服务给DN42用,你可能需要再单独配置端口转发或者veth,但是不在本文讨论范围内。(这也是我实际生产环境最终还是没有采用VRF的原因) VRF的优点 虽然说DN42使用的IP段是私有地址,并且它的ASN用的都是内部ASN,理论上不会和公网BGP相互干扰,但是如果共用同一张路由表,可能会造成路由污染、管理复杂等问题。 VRF(Virtual Routing and Forwarding,虚拟路由转发)可以实现在一台机器上创建多个路由表,也就是说我们可以通过它将DN42的路由单独放到一个路由表里,以实现将DN42路由表和公网路由表相隔离。这么做的优点有: 绝对的安全与策略隔离:DN42路由表和公网路由表相隔离,从根本上杜绝了路由泄露的可能性。 清晰的运维管理:可以使用birdc show route table t_dn42和birdc show route table t_inet来分别查看和调试两张完全独立的路由表,一目了然。 故障域隔离:若果DN42的某个对等体发生Flap,这些影响将被完全限制在dn42的路由表内,不会消耗公网实例的路由计算资源,也不会影响公网的转发性能。 更符合现代网络设计理念:在现代网络工程中,为不同的路由域(生产、测试、客户、合作伙伴)使用VRF是标准做法。它将你的设备逻辑上划分成了多个虚拟路由器。 配置 系统部分 创建VRF设备 使用以下指令创建一个名为dn42-vrf的VRF设备并关联到系统的1042号路由表: ip link add dn42-vrf type vrf table 1042 ip link set dev dn42-vrf up # 启用 路由表号可以按照你自己的喜好修改,但是请避开以下几个保留路由表编号: 名称 ID 说明 unspec 0 未指定,基本不用 main 254 主路由表,大多数普通路由都放在这里 default 253 一般不用,保留 local 255 本机路由表,存放127.0.0.1/8、本机 IP、广播地址等,不能改 将现有的相应网卡关联到VRF 按照我目前的DN42网络为例,有若干WireGuard网卡和一个dummy网卡是用于DN42的,因此将这几个网卡都关联到VRF中: ip link set dev <网卡名> master dn42-vrf 需要注意的是,网卡关联到VRF之后可能会丢失地址,因此需要重新为其添加一次地址,如: ip addr add 172.20.234.225 dev dn42 完成之后,通过ip a应该能看到对应网卡的master是dn42-vrf: 156: dn42: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master dn42-vrf state UNKNOWN group default qlen 1000 link/ether b6:f5:28:ed:23:04 brd ff:ff:ff:ff:ff:ff inet 172.20.234.225/32 scope global dn42 valid_lft forever preferred_lft forever inet6 fd18:3e15:61d0::1/128 scope global valid_lft forever preferred_lft forever inet6 fe80::b4f5:28ff:feed:2304/64 scope link valid_lft forever preferred_lft forever 持久化 我使用了ifupdown2来实现开机自动加载dummy网卡和VRF设备。 auto dn42-vrf iface dn42-vrf inet manual vrf-table 1042 auto dn42 iface dn42 inet static pre-up ip link add $IFACE type dummy || true vrf dn42-vrf address <IPv4 Address>/32 address <IPv6 Address>/128 post-down ip link del $IFACE 我的dummy网卡名称为dn42,如果你的名称不一样请按需要修改。创建完后使用ifup dn42-vrf && ifup dn42即可启动dummy网卡和VRF。 WireGuard隧道 添加PostUp使其关联到vrf并重新为其绑定地址。举个例子: [Interface] PrivateKey = [数据删除] ListenPort = [数据删除] Table = off Address = fe80::2024/64 + PostUp = ip link set dev %i master dn42-vrf + PostUp = ip addr add fe80::2024/64 dev %i PostUp = sysctl -w net.ipv6.conf.%i.autoconf=0 [Peer] PublicKey = [数据删除] Endpoint = [数据删除] AllowedIPs = 10.0.0.0/8, 172.20.0.0/14, 172.31.0.0/16, fd00::/8, fe00::/8 然后重新启动隧道即可。 Bird2部分 首先我们需要定义两张路由表,分别用于dn42的IPv4和IPv6: ipv4 table dn42_table_v4; ipv6 table dn42_table_v6 随后,在kernel protocol中指定VRF和系统路由表编号,并在IPv4、IPv6中指定前面创建的v4、v6路由表: protocol kernel dn42_kernel_v6{ + vrf "dn42-vrf"; + kernel table 1042; scan time 20; ipv6 { + table dn42_table_v6; import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = DN42_OWNIPv6; accept; }; }; }; protocol kernel dn42_kernel_v4{ + vrf "dn42-vrf"; + kernel table 1042; scan time 20; ipv4 { + table dn42_table_v4; import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = DN42_OWNIP; accept; }; }; } 除了kernel以外的protocol都加上VRF和IPv4、IPv6独立的table,但不需要指定系统路由表编号: protocol static dn42_static_v4{ + vrf "dn42-vrf"; route DN42_OWNNET reject; ipv4 { + table dn42_table_v4; import all; export none; }; } protocol static dn42_static_v6{ + vrf "dn42-vrf"; route DN42_OWNNETv6 reject; ipv6 { + table dn42_table_v6; import all; export none; }; } 总而言之就是: 一切和DN42有关的都给配置一个VRF和之前定义的路由表 只有kernel协议需要指定系统路由表编号,其他不需要 对于BGP、OSPF等也如法炮制,不过我选择将公网的RouterID和DN42的分开,因此还需要单独配置一个RouterID: # /etc/bird/dn42/ospf.conf protocol ospf v3 dn42_ospf_iyoroynet_v4 { + vrf "dn42-vrf"; + router id DN42_OWNIP; ipv4 { + table dn42_table_v4; import where is_self_dn42_net() && source != RTS_BGP; export where is_self_dn42_net() && source != RTS_BGP; }; include "ospf/*"; }; protocol ospf v3 dn42_ospf_iyoroynet_v6 { + vrf "dn42-vrf"; + router id DN42_OWNIP; ipv6 { + table dn42_table_v6; import where is_self_dn42_net_v6() && source != RTS_BGP; export where is_self_dn42_net_v6() && source != RTS_BGP; }; include "ospf/*"; }; # /etc/bird/dn42/ebgp.conf ... template bgp dnpeers { + vrf "dn42-vrf"; + router id DN42_OWNIP; local as DN42_OWNAS; path metric 1; ipv4 { + table dn42_table_v4; ... }; ipv6 { + table dn42_table_v6; ... }; } include "peers/*"; 完成后birdc c重载配置即可。 这时,我们可以通过ip route show vrf dn42-vrf来单独查看DN42的路由表: root@iYoRoyNetworkHKGBGP:~# ip route show vrf dn42-vrf 10.26.0.0/16 via inet6 fe80::ade0 dev dn42_4242423914 proto bird src 172.20.234.225 metric 32 10.29.0.0/16 via inet6 fe80::ade0 dev dn42_4242423914 proto bird src 172.20.234.225 metric 32 10.37.0.0/16 via inet6 fe80::ade0 dev dn42_4242423914 proto bird src 172.20.234.225 metric 32 ... 也可以在Ping的时候通过参数-I dn42-vrf来实现通过VRF Ping: root@iYoRoyNetworkHKGBGP:~# ping 172.20.0.53 -I dn42-vrf ping: Warning: source address might be selected on device other than: dn42-vrf PING 172.20.0.53 (172.20.0.53) from 172.20.234.225 dn42-vrf: 56(84) bytes of data. 64 bytes from 172.20.0.53: icmp_seq=1 ttl=64 time=3.18 ms 64 bytes from 172.20.0.53: icmp_seq=2 ttl=64 time=3.57 ms 64 bytes from 172.20.0.53: icmp_seq=3 ttl=64 time=3.74 ms 64 bytes from 172.20.0.53: icmp_seq=4 ttl=64 time=2.86 ms ^C --- 172.20.0.53 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3006ms rtt min/avg/max/mdev = 2.863/3.337/3.740/0.341 ms 注意事项 如果vrf设备重载了,所有原先和vrf相关联的设备都需要重载一次,否则无法正常工作 目前DN42是无法访问到配置了VRF的主机内的服务的,后续可能出一篇文章讲一下如何去让VRF内的流量可以访问到主机服务(挖坑ing) 参考文章: 用 BIRD 运行你的 MPLS 网络
2025年09月16日
86 阅读
0 评论
0 点赞
通过PBR为双网卡VPS配置多出口路由
水文警告 背景 从朋友那里弄到一台深港IEPL机器,有两个网卡eth0和eth1,但是默认都走eth0,eth1没有配置路由。 我打算通过metric实现粗略的分流再通过PBR实现按照规则的路由配置。 配置 机器默认由cloudinit配置了网卡: # This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-init's # network configuration capabilities, write a file # /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following: # network: {config: disabled} network: version: 2 ethernets: eth0: addresses: - 10.10.1.31/16 gateway4: 10.10.0.1 match: macaddress: bc:24:11:f8:42:7a nameservers: addresses: - 223.5.5.5 - 119.29.29.29 search: - [数据删除] set-name: eth0 eth1: addresses: - 10.20.1.31/16 - [数据删除]/64 gateway4: 10.20.0.1 gateway6: fe80::be24:11ff:fe80:66bb match: macaddress: bc:24:11:50:96:0a nameservers: addresses: - 223.5.5.5 - 119.29.29.29 search: - [数据删除] set-name: eth1 备份一份配置之后加上metric: # This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-init's # network configuration capabilities, write a file # /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following: # network: {config: disabled} network: version: 2 ethernets: eth0: addresses: - 10.10.1.31/16 gateway4: 10.10.0.1 match: macaddress: bc:24:11:f8:42:7a nameservers: addresses: - 223.5.5.5 - 119.29.29.29 search: - [数据删除] set-name: eth0 + routes: + - to: "default" + via: "10.10.0.1" + # 设置 metric=50,作为备选出口 + metric: 50 eth1: addresses: - 10.20.1.31/16 - [数据删除]/64 gateway4: 10.20.0.1 gateway6: fe80::be24:11ff:fe80:66bb match: macaddress: bc:24:11:50:96:0a nameservers: addresses: - 223.5.5.5 - 119.29.29.29 search: - [数据删除] set-name: eth1 + routes: + - to: "default" + via: "10.20.0.1" + # 设置 metric=25,作为优先出口 + metric: 25 编写PBR配置: # /etc/netplan/90-pbr.yaml network: version: 2 ethernets: eth0: routes: - to: default via: 10.10.0.1 table: 10 routing-policy: - from: 10.10.0.0/16 table: 10 - to: 202.46.[数据删除]/32 table: 10 eth1: routes: - to: default via: 10.20.0.1 table: 20 routing-policy: - from: 10.20.0.0/16 table: 20 - to: 38.47.[数据删除]/32 table: 20 - to: 23.149.[数据删除]/32 table: 20 对于需要指定出口访问的IP为其加上to类型的规则并绑定对应路由表即可。 完成后运行 netplan apply 更新配置
2025年09月14日
67 阅读
0 评论
0 点赞
OneManISP - Ep.2 向世界宣告我们自己的IP段
前言 上文我们已经成功注册了一个ASN并且拿到了一段IPv6地址,这次我们就来将这段地址广播给全世界。 在RIPE Database设置子网对象 需要注意的是,公网允许广播的最小IPv6前缀是/48,也就是说你如果只有一个/48地址你无法将其拆成更小的段。所以我后来又单独租用了一段/40,打算将其拆成多个/48来广播。 我获取到的IPv6为2a14:7583:f200::/40,打算拆出来2a14:7583:f203::/48用于给Vultr使用。如果你不需要拆段,请直接跳转到「创建路由信息」一节 拆段 首先打开Create "inet6num" object - RIPE Database,填入如下内容: inet6num: 打算拆出来的IP段,CIDR格式 netname: 网络名称 country: IP段所属国家,需要符合ISO 3166标准(RIPE DB里可以直接选择) admin-c: 上文创建的Role对象的主键值 tech-c: 上文创建的Role对象的主键值 status: ASSIGNED即可 此步骤将你获得的地址拆出来一个小的/48地址块。 创建路由信息 打开Create "route6" object - RIPE Database,填入如下内容: route6: 填写你打算广播播的IPv6地址块的CIDR格式 origin: 填写你申请到的ASN,包含AS前缀 此步骤声明允许你的ASN使用这段地址段来发BGP路由。 申请VPS的BGP Session接入 此次我使用的是Vultr家的机器,他们家的BGP Session算是很新手友好的了,有一套自己的验证系统;并且上游良好的过滤器保证了一般情况下即使发送了错误的路由表也不会影响到公网。 (此处我配置的时候忘记截图了,可以参考一下宝硕大佬的文章 年轻人的第一个 ASN 中的 申请 Vultr 的 BGP 广播功能 章节) 进入BGP - Vultr.com,选择Get Started之后按照要求填写你的ASN信息和IPv6地址块。LOA(Letter Of Authorization,授权信)可参考以下模板:LOA-template.docx(因为发现网上查到的都是以公司的名义写的,因此以个人名义重新写了一份) 完成后系统会自动创建一条工单,并且能看到我们的ASN和IP地址块处于待验证的状态: 点击Start,系统会向注册Role时填写的abuse-mailbox邮箱发送一封验证邮件: 收到的邮件如图所示: 其中,上面那个链接代表同意授权Vultr广播你的IP段,下面那个则是不同意。我们点击上面那个之后会进入Vultr的网页: 再点击Approve Announcement即可。ASN和IP段都需要验证一次。 接着,等待Vultr的工作人员审核完成后来到VPS的控制台,就能看到我们的BGP选项卡了,其中可以得到上游的信息: 此处不得不称赞一下Vultr的工单效率,我平均从创建工单申请授权到完成只花了10分钟左右。(反观之前在iFog GmbH,平均工作日工单回复时间1天左右实在是好太多了) 其他厂商的VPS大概都是这么个流程,你需要告诉工作人员你要播的ASN和IP段,在验证完所有权之后工作人员会为你配置对应的BGP Session。 广播! 你应该已经从上游那里得到了以下信息: 上游的ASN 上游用于BGP Session的地址 (可选)密码 我用的操作系统是Debian12 Bookworm,使用Bird2作为路由软件,并且按照这篇文章中「更新Bird2至v2.16及以上」章节更新Bird2至最新版。Vultr那边给我的上游ASN是64515,上游用于BGP Session的地址是2001:19f0:ffff::1,VPS用于BGP Session的地址是2001:19f0:0006:0ff5:5400:05ff:fe96:881f。 我的Bird2配置文件修改自DN42中的配置文件: log syslog all; define OWNAS = 205369; # 自己的ASN define OWNIPv6 = 2a14:7583:f203::1; # 给机器绑定的单个IPv6地址 define OWNNETv6 = 2a14:7583:f203::/48; # 打算播的网段 define OWNNETSETv6 = [ 2a14:7583:f203::/48+ ]; # 打算播的网段集合 router id 45.77.x.x; # 路由器ID,这里使用VPS的公网IPv4 protocol device { scan time 10; } function is_self_net_v6() { return net ~ OWNNETSETv6; } protocol kernel { scan time 20; ipv6 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIPv6; accept; }; }; }; protocol static { route OWNNETv6 reject; ipv6 { import all; export none; }; } template bgp upstream { local as OWNAS; path metric 1; multihop; # 指定多跳 ipv6 { import filter { if net ~ [::/0] then reject; # 拒绝导入默认路由 accept; }; export filter { if is_self_net_v6() then accept; # 仅导出自己网段内的路由,防止劫持 reject; }; import limit 1000 action block; }; graceful restart; } protocol bgp 'Vultr_v6' from upstream{ local 2001:19f0:0006:0ff5:5400:05ff:fe96:881f as OWNAS; # local后面的地址即上游给的用于BGP Session的VPS上的地址 password "123456"; # 上游给你的BGP密码,若没密码就将这一行删除 neighbor 2001:19f0:ffff::1 as 64515; # 上游的BGP Session IP和ASN } 几个值得注意的点: 此处upstream模板的导入规则拒绝了 默认路由 ,这样写可以防止上游发来的路由表覆盖掉本地的默认网关等路由信息。如果我们有多个BGP邻居,则可能导致绕路甚至路由环路。 upstream中指定了多跳(multihop;),这是因为Vultr的BGP对端不能直达,若不设置多跳则会导致BGP会话卡在Idle状态。如果你的BGP上游是直连,可以不设置此行或者改为direct;。 填写完配置文件,运行birdc configure载入配置。 运行birdc show protocols查看状态,如果不出意外的话应该能看到BGP会话已经Established: 这个时候,你可以起身做点别的事情,等待全球路由收敛。大概半个小时之后,打开bgp.tools,查询自己的/48段,应该就能看到已经成功被全球互联网收敛,并且能看到我们的上游信息: 接着,我们在VPS上创建一个dummy网卡,并绑定我们为这个机器设置的段内的单个IPv6地址,如我给我这台机器分配了2a14:7583:f203::1: ip link add dummy0 type dummy ip addr add 2a14:7583:f203::1/128 dev dummy0 接着使用我们自己的PC ping这个地址就能通了,traceroute也能看到完整路由路径: 感谢米露大佬提供的技术支持! 参考文章: 自己在家开运营商 Part.2 - 向世界宣告 IP 段 (BGP Session & BIRD) 年轻人的第一个 ASN - 宝硕博客 BGPlayer 从零开始速成指北 - 开通 Vultr 的 BGP 广播功能 - AceSheep BGP (2) 在 Vultr 和 HE 使用自己的 IPV6 地址 - 131's Blog
2025年08月20日
120 阅读
0 评论
1 点赞
OneManISP - Ep.1 注册一个ASN
写在前面 本文记录了我在RIPE NCC申请ASN的完整过程,内容适合入门者参考,若有错误欢迎邮件联系我,我会在第一时间更正。 既然已经在DN42上学习了基本的BGP概念,不玩玩公网的有点说不过去吧( 基本概念 目前公网ASN和IP资源分配由世界上5个 区域互联网注册管理机构(Regional Internet registry, RIR) 管理: ARIN: 负责管理北美地区 RIPE NCC: 负责管理欧洲地区 APNIC: 亚洲地区 LACNIC: 拉丁美洲地区 AfriNIC: 非洲地区 RIR不直接对个人用户提供服务,而是通过将资源授权给 本地互联网注册管理机构(Local Internet Registry, LIR) ,再由LIR授权给个人。当然,个人用户也可以注册成为LIR,但是这一般而言一般是不划算的。 如果你愿意每年交几千美元作为会费的话当我没说。 其中,对个人申请比较友好的是RIPE NCC,其次是ARIN和APNIC。相较于RIPE NCC,APNIC的费用普遍要高30%左右;并且RIPE NCC提供了一套在线管理系统,用户可以自己修改信息、查询进度,而在APNIC则需要联系LIR处理。综合而言,我选择在RIPE NCC申请ASN。 申请到的资源(ASN、IP都算)一般分为两种: PA(Provider Aggregatable)资源: 属于LIR,由LIR注册授权给你用的资源 PI(Provider Independent)资源: 属于你自己的资源,一般而言价格较高 准备阶段 选择一个LIR 上网查询LIR Service,可以找到很多提供这类服务的商家。目前RIPE NCC会向PI资源收取一年50EUR的管理费用,也就是说一般而言LIR注册ASN的费用不会低于50EUR(截至文章发布,大概60USD)一年。此处我选择的群友推荐的NoPKT LLC,价格算是比较合理的并且随ASN附赠一段/48 PA IPv6地址,实测下号速度也很快,从提交完材料到下号只用了半天。 准备材料 身份证明 个人:提供身份证或者护照都可以(我提供的身份证正反面照片) 企业:提供有效的营业执照 若申请人为未成年人,通常需要其法定监护人提供书面同意书并履行相应监护职责。所有提交的文件应确保真实有效,且必须是原件或经过公证的副本。 联系信息 通信地址,被用于登记在RIPE Database 技术人员邮箱 滥用举报邮箱 技术要求证明 欧洲范围内的BGP服务商开具的账单,可以选择Vultr、BuyVM、iFog、V.PS等。 注:Vultr是先用后付制,每月初出账单。如果你着急备好材料,建议选择其他家。 两个你打算接入的上游的ASN(实际上审核方不会严格验证你填写的上游ASN,因此可以随意填写,但建议填写一些常见的公开ASN以显得合理,不用过多纠结。 甚至填我的也行 ) 注册RIPE DB账户并创建条目 打开RIPE Database并注册一个账户。此处填写姓名时建议填写你自己的真实姓名的拼音,并且强制要求开启2FA,请提前在手机上安装TOTP软件。 创建Role对象和Maintainer对象 打开Create role and maintainer pair - RIPE Database,创建一个role对象。 此处role为一个抽象概念,用来描述一个团队、部门或者职能角色的联系方式,代指一个角色,比如 NOC (Network Operations Center)、Abuse Team、Hostmaster 等。 mntner: maintainer对象的标识符,可包含大小写字母、数字、-_。例如我填写的是IYOROY-MNT role: role对象的名称,可包含大小写字母、数字、][)(._"*@,&:!'+/-。例如我填写的是IYOROY-NETWORK-NOC address: 此role对象的办公地址 e-mail: 此role的电子邮件地址 填写完成后SUBMIT即可创建role对象和maintainer对象。请记录下返回的主键名称,一般以-RIPE结尾,后续修改信息及提交到LIR需要用到。 此处maintainer对象标识符和role对象有所区别,前者意为谁有权限维护数据库中的对象(即写入/修改/删除权限控制),是维护者实体。关于RIPE Database中各个概念之间的归属,可参考文章后部的示意图。 添加滥用举报邮箱 打开Query - RIPE Database,查询刚刚获得的role主键名称,可以查询到刚刚创建的条目。点击右侧Update Object。 点击e-mail栏右侧的加号,创建一个abuse-mailbox属性,并且填入你的滥用举报邮箱: SUBMIT保存。 注:RIPE会定时检查滥用举报邮箱是否可用,请务必填写真实的邮箱地址 创建Organization对象 此处Organization对象是法律实体或组织(公司、大学、ISP、个人用户等)的抽象,是 RIPE Database 里资源对象(比如aut-num、inetnum、inet6num)的上层归属信息,也就是说后续的ASN、IP资源都将授权给Organization对象。 打开Create Organization - RIPE Database,填写如下信息: organisation: 唯一ID,保留为默认的AUTO-1即代表由RIPE NCC分配。 org-name: 组织的名称。如果是个人用户注册则需要填写你自己的姓名拼音全称。 address: 通信地址。 country: 国家代码,参考ISO 3166。中国就填写CN e-mail: 组织的电子邮件。 admin-c / tech-c: 联系对象(引用 role 的 handle)。 abuse-c: 指定abuse联系方式(必须是一个role对象,链接到role对象中的abuse-mailbox)。 mnt-ref: 指定可以创建引用该organisation的对象的维护者。 mnt-by: 谁能维护这个organisation本身。 填写完SUBMIT,并记下返回的对象标识符,类似于ORG-XXXX-RIPE的格式。 如果你在提交后发现需要修改,去Query - RIPE Database查找刚刚记录下的Role主键或者组织的对象标识符即可找到修改入口。 支付LIR费用并且提交材料 将以下材料提交给你的LIR: 身份证明 姓名 地址,推荐证件地址 身份证正反面照片 RIPE Database信息 org: 组织对象标识符 as-name: AS名称 admin-c: 上面创建的role对象主键 tech-c: 上面创建的role对象主键 abuse-c: 上面创建的role对象主键 nic-handle: 上面创建的role对象主键 mnt-by: 上面创建的maintainer对象名称 技术要求证明 VPS账单 上游的ASN LIR会要求你在你的Organization里添加一条mnt-ref,指向LIR的维护者,这样LIR那边才能够将AS和IP等资源授权到你的Organization。LIR那边审核没问题之后会将请求提交到RIPE,接着就是等待。一般而言需要3-5个工作日即可下号。 自此,我们已经在公网上注册了属于我们自己的ASN。 补充:RIPE Database中各个概念之间的关系 graph LR %% ========== ORG 层 ========== subgraph Org["Organisation"] ORG["organisation\n(ORG-XXX-RIPE)"] end %% ========== 资源层 ========== subgraph Resource["资源"] INETNUM["inetnum\n(IPv4 段)"] INET6NUM["inet6num\n(IPv6 段)"] AUTNUM["aut-num\n(ASN)"] ASSET["as-set\n(ASN 集合)"] end %% ========== 路由层 ========== subgraph Routing["路由"] ROUTE["route\n(IPv4 前缀公告)"] ROUTE6["route6\n(IPv6 前缀公告)"] end %% ========== 联系人层 ========== subgraph Contact["联系人"] ROLE["role\n(团队/职能)\nnic-hdl"] PERSON["person\n(个人)\nnic-hdl"] end %% ========== 权限层 ========== subgraph Maintainer["权限"] MNT["mntner\n(维护者)"] end %% ========== 联系 ========== INETNUM --> ROLE INET6NUM --> ROLE AUTNUM --> ROLE ASSET --> ROLE ROUTE --> ROLE ROUTE6 --> ROLE ROLE --> PERSON %% ========== 组织归属 ========== ORG --> INETNUM ORG --> INET6NUM ORG --> AUTNUM ORG --> ASSET %% ========== 权限 ========== ORG --> MNT INETNUM --> MNT INET6NUM --> MNT AUTNUM --> MNT ASSET --> MNT ROUTE --> MNT ROUTE6 --> MNT ROLE --> MNT PERSON --> MNT %% ========== 路由绑定 ========== ROUTE -->|origin| AUTNUM ROUTE6 -->|origin| AUTNUM %% ========== 路由范围 ========== ROUTE -->|属于| INETNUM ROUTE6 -->|属于| INET6NUM 特别感谢米露大佬提供部分技术支持和答疑解惑! 参考文章: 自己在家开运营商 Part.1 - 注册一个 ASN - LYC8503 从0开始注册一个ASN并广播IP | Pysio's Home 青年人的第一个运营商:注册一个 ASN | liuzhen932 的小窝
2025年08月18日
172 阅读
0 评论
1 点赞
1
2