Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ generate_mac() {

平常使用直接 `./generate_mac.sh` 运行就行

## ipv4.sh
## ip.sh

用来通过 Cloudflare 绑定的域名进行内网 DDNS 的脚本,目的是为了在大内网的其他地方也能够访问到内网的设备

需要自己调整 Cloudflare 的相关内容

新版本同时支持 v6 & v4,只需要配置或留空对应的位置即可

```bash
# Cloudflare API 相关信息
# Cloudflare API 端点,替换为实际的 API URL
Expand All @@ -40,6 +42,9 @@ CF_TOKEN=""
CF_DOMAIN=""
```

<<<<<<< HEAD
平时使用直接 `./ip.fish` 运行就行
=======
`zone_id` 是你的 Cloudflare 的区域 ID,在域名的概览下就有

![](https://bili33.eu.org/file/VkGuUz9S.png)
Expand Down Expand Up @@ -75,13 +80,32 @@ EOF
通过对网关进行 ping 操作来判断机身是否断开 pppoe 连接,需要与 `generate_mac.sh` 和 `ipv4.sh` 一起使用(DDNS 脚本不用的话注释掉就行)

建议开机运行
>>>>>>> upstream/fish

## swap.sh

调整机身的 swap 分区的脚本,避免因软路由自身内存限制导致很多软件无法运行

直接 `./swap.sh` 运行就行

## kc.fish

Keep Connection - 自动检测连接状态并在断线或者新设备加入触发设备踢出时重拨

使用方法:
```bash
./kc.fish
```

配置说明(在脚本开头可配置):
- `max_retry`: 最大重试次数(默认30次)
- `sleep_time`: 重拨后等待网络稳定时间(秒,默认10秒)
- `overhead_interval`: 正常状态检测间隔(秒,默认3秒)
- `max_fail`: 最大连续失败次数(触发重拨,默认3次)
- `ping_target`: 检测连接的目标地址(默认 https://baidu.com)

脚本会持续运行,建议通过 `screen` 或 `tmux` 后台运行

## utils.sh

Openwrt 备份脚本,注意自己调整备份文件保存的位置,建议使用 SMB 存储或者插个 U 盘
Expand Down
1 change: 1 addition & 0 deletions scripts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.envrc
16 changes: 8 additions & 8 deletions scripts/generate_mac.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

# 生成一个随机的MAC地址
generate_mac() {
# 固定的前缀,格式为 aa:bb:cc
PREFIX=""
# 使用 /dev/urandom 获取随机数
HEX1=$(hexdump -n 1 -e '1/1 "%02X"' /dev/urandom)
HEX2=$(hexdump -n 1 -e '1/1 "%02X"' /dev/urandom)
HEX3=$(hexdump -n 1 -e '1/1 "%02X"' /dev/urandom)
echo "$PREFIX:$HEX1:$HEX2:$HEX3"
# 固定的前缀,格式为 aa:bb:cc
# PREFIX=""

# 使用 /dev/urandom 获取随机数
HEX1=$(hexdump -n 1 -e '1/1 "%02X"' /dev/urandom)
HEX2=$(hexdump -n 1 -e '1/1 "%02X"' /dev/urandom)
HEX3=$(hexdump -n 1 -e '1/1 "%02X"' /dev/urandom)
echo "$PREFIX:$HEX1:$HEX2:$HEX3"
}

# 获取新的MAC地址
Expand All @@ -22,4 +23,3 @@ ip link set dev eth0 up

# 验证修改是否成功
ip link show eth0 | grep ether

114 changes: 31 additions & 83 deletions scripts/ipv4.fish → scripts/ip.fish
Original file line number Diff line number Diff line change
@@ -1,65 +1,54 @@
#!/usr/bin/env fish

# Cloudflare Dynamic DNS Updater (IPv4 & IPv6)
# 自动更新 Cloudflare DNS 记录为当前 PPPoE 拨号的内网 IP 地址
# 自动更新 Cloudflare DNS 记录为当前 default route 的 IP 地址
# 支持同时更新 IPv4 (A 记录) 和 IPv6 (AAAA 记录)
# 如果不需要更新某种类型的记录,请将对应的域名设为空,ID 可以留空以启用自动检测

source utils_lib.fish

# Cloudflare Zone ID
# DNS 配置主界面(https://dash.cloudflare.com/<ACCOUNT_ID>/<DOMAIN>) > API
set -g ZONE_ID xxx
# set ZONE_ID

# Cloudflare API Token
set -g TOKEN xxx
# set TOKEN

# IPv4 配置 (如果不需要 IPv4 更新,请将这些变量设为空)
# RECORD_ID 可以通过 API 获取
set -g IPV4_DOMAIN ""
set -g IPV4_RECORD_ID ""
# set IPV4_DOMAIN
# 留空以启用自动检测
# set IPV4_RECORD_ID

# IPv6 配置 (如果不需要 IPv6 更新,请将这些变量设为空)
set -g IPV6_DOMAIN ""
set -g IPV6_RECORD_ID ""

# PPPoE 接口名称(根据实际情况修改)
set -g PPPOE_INTERFACE pppoe-wan
# set IPV6_DOMAIN
# 留空以启用自动检测
# set IPV6_RECORD_ID

# DNS 记录配置
set -g DNS_TTL 120
set -g DNS_PROXIED false
set DNS_TTL 120
set DNS_PROXIED false

# 全局正则表达式映射
set -g regex_A '^([0-9]{1,3}\.){3}[0-9]{1,3}$'
set -g regex_AAAA '^([0-9A-Fa-f]{0,4}:){2,7}[0-9A-Fa-f]{0,4}$'

# =============================================================================
# 辅助函数
# =============================================================================

function log_info
printf "\033[36m%s %s\033[0m\n" "[INFO]" (string join " " $argv) >&2
end

function log_error
printf "\033[31m%s %s\033[0m\n" "[ERROR]" (string join " " $argv) >&2
end

function log_success
printf "\033[32m%s %s\033[0m\n" "[SUCCESS]" (string join " " $argv) >&2
end

function validate_ip

set -l regex_A '^([0-9]{1,3}\.){3}[0-9]{1,3}$'
set -l regex_AAAA '^([0-9A-Fa-f]{0,4}:){2,7}[0-9A-Fa-f]{0,4}$'

set -l type $argv[1]
set -l ip $argv[2]
set -l regex (eval echo \${regex_$type})
string match -q -r $regex $ip
end

function get_pppoe_ip
function get_ip
set -l type $argv[1]
set -l flag (string match -q A $type; and echo -4; or echo -6)
set -l filter (string match -q A $type; and echo inet; or echo inet6.*global)
set -l ip (ip $flag addr show $PPPOE_INTERFACE 2>/dev/null | awk "/$filter/ {print \$2}" | cut -d'/' -f1 | head -n 1)
switch $type
case A
set ip (ip -4 route | grep "default" | awk '{print $NF}')
case AAAA
set ip (ip -6 addr show scope global | grep inet6 | head -1 | awk '{print $2}' | cut -d'/' -f1)
end
test -n "$ip"; or begin log_error "获取 $type 地址失败: $ip"; return 1; end
validate_ip $type $ip; or begin log_error "$type 地址格式无效: $ip"; return 1; end
echo $ip
Expand All @@ -72,10 +61,9 @@ function get_dns_record

log_info "获取 $type 记录..."
curl -s -X GET $url -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" | read -l response; or begin log_error "请求失败"; return 1; end
string match -q '"success":true' $response; or begin log_error "Cloudflare API 错误: $response"; return 1; end
string match -q '*"success":true*' $response; or begin log_error "Cloudflare API 错误: $response"; return 1; end

set -l regex (eval echo \${regex_$type})
set -l ip (string match -r -o $regex $response)
set -l ip (echo $response | sed -n 's/.*"content":"\([^" ]*\)".*/\1/p')

test -n "$ip"; or begin log_error "未提取到 IP"; return 1; end
validate_ip $type $ip; or begin log_error "IP 格式无效: $ip"; return 1; end
Expand Down Expand Up @@ -149,38 +137,6 @@ function update_cloudflare_dns_record
end
end # update_cloudflare_dns_record 函数结束

# =============================================================================
# 自动检测并更新 Record ID
# =============================================================================
function auto_detect_record_id
# 参数: record_type, domain, record_id_var_name
set -l record_type $argv[1]
set -l domain $argv[2]
set -l record_id_var_name $argv[3]

if test -z "$domain"
# 未配置域名, nothing to do
return
# 尝试解析错误信息
set -l error_msg (echo $response | sed -n 's/.*"message":"\([^"]*\)".*/\1/p')
if test -n "$error_msg"
log_error "错误信息: $error_msg"
end

# 检查常见错误原因
if string match -q "*authentication*" $response
log_error "认证失败,请检查 TOKEN 是否正确"
else if string match -q "*not found*" $response
log_error "DNS 记录未找到,请检查 Record ID 是否正确"
else if string match -q "*invalid*" $response
log_error "请求参数无效,请检查配置"
end

log_error "完整响应内容: $response"
return 1
end
end # update_cloudflare_dns_record 函数结束

# =============================================================================
# 自动检测并更新 Record ID
# =============================================================================
Expand Down Expand Up @@ -212,10 +168,12 @@ function auto_detect_record_id
set -l id (echo $resp | awk -F'"id":' '{print $2}' | cut -d '"' -f2 | head -n 1)
if test -n "$id"
log_success "$record_type Record ID 获取成功: $id"
# 确保变量定义未被注释
sed -i "s@^#\s*set $record_id_var_name@set $record_id_var_name@" (status --current-filename)
# 更新运行时变量
set -g $record_id_var_name $id
set $record_id_var_name $id
# 自我更新脚本文件中对应行
sed -i "s@set -g $record_id_var_name.*@set -g $record_id_var_name \"$id\"@" (status --current-filename)
sed -i "s@set $record_id_var_name.*@set $record_id_var_name \"$id\"@" (status --current-filename)
# 返回 id 以便调用处捕获
echo $id
return 0
Expand All @@ -231,27 +189,17 @@ end

log_info "开始检查 Cloudflare DNS 记录更新..."

# 自动检测并更新 Record ID
# auto_detect_record_id A IPV4_DOMAIN IPV4_RECORD_ID
# auto_detect_record_id AAAA IPV6_DOMAIN IPV6_RECORD_ID

# 在主循环中按需自动检测 Record ID(也可单独调用)
# auto_detect_record_id A "$IPV4_DOMAIN" IPV4_RECORD_ID
# auto_detect_record_id AAAA "$IPV6_DOMAIN" IPV6_RECORD_ID

set -l record_var_names IPV4_RECORD_ID IPV6_RECORD_ID

# 支持的记录类型数组
set -l types A AAAA
set -l domains $IPV4_DOMAIN $IPV6_DOMAIN
set -l record_ids $IPV4_RECORD_ID $IPV6_RECORD_ID
set -l pppoe_funcs get_pppoe_ipv4 get_pppoe_ipv6

for i in (seq (count $types))
set -l type $types[$i]
set -l domain $domains[$i]
set -l record_id $record_ids[$i]
set -l pppoe_func $pppoe_funcs[$i]
set -l record_var_name $record_var_names[$i]

if test -z "$domain"
Expand All @@ -271,7 +219,7 @@ for i in (seq (count $types))

log_info "=== 处理 $type 记录 ($domain) ==="
# 获取本地 IP
set -l local_ip ($pppoe_func)
set -l local_ip (get_ip $type)
if test $status -ne 0
log_error "获取本地 $type 地址失败,跳过"
continue
Expand Down
63 changes: 0 additions & 63 deletions scripts/ipv4.sh

This file was deleted.

49 changes: 49 additions & 0 deletions scripts/kc.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env fish

# Keep Connection - 自动检测连接状态并在断线时重拨

source utils_lib.fish

# 重试配置
set max_retry 30 # 最多重试次数

# 设置重拨后休眠时间(秒)
set sleep_time 10
set overhead_interval 3
set max_fail 3

# TODO: 其实这里不需要 ping 只需要 访问一个 http 网站检测是否重定向就可以了
set ping_target "https://baidu.com"

function reconnect
echo "Network appears to be down... Reconnecting..."
/root/generate_mac.sh
while true
set gateway (ip route | grep "default via" | awk '{print $3}')
if test -n "$gateway"
log_success "Gateway detected: $gateway"
break
end
end
/root/login.fish
sleep 25
/root/ip.fish
echo "Waiting for network to stabilize..."
sleep $sleep_time
echo "Attempting to get new gateway address after reconnection..."
end

while true
set count 0
while not curl -I --connect-timeout 1 $ping_target >/dev/null 2>&1
set count (math "$count + 1")
if test $count -gt $max_fail
reconnect
break
end
log_info "Ping to target $ping_target failed. Failure count: $count. Retrying..."
end
log_success "Ping to target $ping_target successful."

sleep $overhead_interval
end
Loading