OpenWrt 使用

[toc]

交叉编译工具链

musl 工具链 https://musl.cc/

ipv6

ipv6 需要开启防火墙 wan 的 546 udp 入站

如果需要配置多个隔离的 lan 口的话,IPv6 分配长度至少设置为运营商分配 PD 前缀 +4,同时每个 lan 口设置不同的 ipv6 前缀,这样子在 ipv6 层面才是划分为不同的子网,不然仅会有一个 lan 口能获取到 ipv6 地址

第三方源

src/gz dllkids https://op.dllkids.xyz/packages/aarch64_generic/

DDNS

开机自启

将 /etc/init.d/ddns 中 boot 函数删除,或者在 boot 中调用 start 函数

阿里云

获取 AccessKey

打开 RAM 访问控制 https://ram.console.aliyun.com/overview

点击左侧 用户 -> 创建用户

创建用户时,勾选 “OpenAPI 调用访问”,记住 AccessKey,一次性的,页面关闭后就找不到了,一定要记住

创建完成后授予如下两个权限

01

配置阿里云解析

https://github.com/renndong/ddns-scripts-aliyun

文件来自上述链接,也可以直接手动放到对应目录下

/usr/lib/ddns/update_aliyun_com.sh

#!/bin/sh
#
#.Distributed under the terms of the GNU General Public License (GPL) version 2.0
# 2023 ren dong <lml256@foxmail.com>
#
# Aliyun DNS Documentation at https://help.aliyun.com/document_detail/29742.html
#
# This script is parsed by dynamic_dns_functions.sh inside send_update() function
#
# using following options from /etc/config/ddns
# option username - AccessKeyID generated by Aliyun
# option password - AccessKeySecret generated by Aliyun
# option domain   - "hostname@yourdomain.TLD" or "@yourdomain.TLD"
#
# variable __IP already defined with the ip-address to use for update
#

# check parameters
[ -z "$CURL" ] && [ -z "$CURL_SSL" ] && write_log 14 "Communication require cURL with SSL support. Please install"
[ -z "$username" ] && write_log 14 "Service section not configured correctly! Missing key as 'username'"
[ -z "$password" ] && write_log 14 "Service section not configured correctly! Missing secret as 'password'"

. /usr/share/libubox/jshn.sh

local __RR __HOST __DOMAIN __TYPE

# split __RR __DOMAIN from $domain
__RR=$(printf '%s' "$domain" | cut -d@ -f1)
__DOMAIN=$(printf '%s' "$domain" | cut -d@ -f2)

[ -z "$__RR" ] && {
    __RR="@" && __HOST="$__DOMAIN"
} || __HOST="$__RR.$__DOMAIN"

# set record type
[ "$use_ipv6" -eq 0 ] && __TYPE="A" || __TYPE="AAAA"

# set API URL base
__URLBASE="https://alidns.aliyuncs.com/?"

# encode params using RFC3986 rule
encode_url_component() {
    local __STR1 __STR2 __INDEX
    __STR1=$(printf -- '%s' "$1" | $CURL -Gso /dev/null -w '%{url_effective}' --data-urlencode @- "aliyun.com" | cut -d "?" -f 2)
    __STR2=""
    __INDEX=0
    # convert the two hex numbers after '%' to uppercase
    # we need uppercase hex, and use the above code is enough on other linux platform. but
    # the curl of openwrt is a little bit different to other versions, i dont know why
    while [ "$__INDEX" -lt ${#__STR1} ]; do
        if [ "${__STR1:$__INDEX:1}" = "%" ]; then
            __STR2="$__STR2$(printf -- '%s' "${__STR1:$__INDEX:3}" | tr [a-z] [A-Z])" && __INDEX=$((__INDEX + 3))
        else
            __STR2="$__STR2${__STR1:$__INDEX:1}" && __INDEX=$((__INDEX + 1))
        fi
    done
    printf -- '%s' "$__STR2"
}

do_request() {
    local __COMMON_PARAMS __CANONICALIZED_QUERY_STRING __STRING_TO_SIGN __SIGNATURE
    local __PROGRAM __HTTP_CODE __ERR
    __COMMON_PARAMS="Format=JSON
                  Version=2015-01-09
                  AccessKeyId=$username
                  SignatureMethod=HMAC-SHA1
                  SignatureVersion=1.0
                  Timestamp=$(encode_url_component "$(date -u +"%Y-%m-%dT%H:%M:%SZ")")
                  SignatureNonce=$(head /dev/urandom | tr -dc '0123456789' | head -c16)"

    # build canonicalized query string, notice we use ascii order when sorting
    __CANONICALIZED_QUERY_STRING="$(printf -- '%s' "$__COMMON_PARAMS $*" | sed 's/\s\+/\n/g' | LC_COLLATE=C sort | xargs | sed 's/\s/\&/g')"

    # calculate signature
    __STRING_TO_SIGN="GET&$(encode_url_component "/")&$(encode_url_component "$__CANONICALIZED_QUERY_STRING")"
    __SIGNATURE="$(printf -- '%s' "$__STRING_TO_SIGN" | openssl sha1 -binary -hmac "$password&" | openssl base64)"
    __SIGNATURE="Signature=$(encode_url_component "$__SIGNATURE")"

    __PROGRAM="$CURL -sSL -o $DATFILE --stderr $ERRFILE -w '%{http_code}' \"$__URLBASE$__CANONICALIZED_QUERY_STRING&$__SIGNATURE\""

    write_log 7 "Run command #> $__PROGRAM"
    __HTTP_CODE=$(eval "$__PROGRAM")
    __ERR=$?
    [ "$__ERR" -eq 0 ] && [ "$__HTTP_CODE" -eq 200 ] || {
        write_log 3 "Run command got error, curl err: $__ERR, http_code: $__HTTP_CODE"
        write_log 7 "DATFILE: $(cat "$DATFILE") ERRFILE $(cat "$ERRFILE")"
        return 1
    }
}

do_request "Action=DescribeSubDomainRecords" \
    "DomainName=$(encode_url_component "$__DOMAIN")" \
    "Type=$__TYPE" \
    "SubDomain=$(encode_url_component "$__HOST")" || return 1

# load record id and record value from the response
json_load_file "$DATFILE"
json_get_var __RECORD_COUNT TotalCount

# if no record found, report error
[ "$__RECORD_COUNT" -eq 0 ] && {
    write_log 7 "DNS record of $__HOST is not exist."
    return 1
}

# if multiple records are found, only use the first one
[ "$__RECORD_COUNT" -gt 1 ] && {
    write_log 4 "WARNING: found multiple records of $__HOST, only use the first one"
}

# select the first DNS record
json_select DomainRecords
json_select Record
json_select 1
# get the record id of the first DNS record
json_get_var __RECORD_ID RecordId
json_get_var __RECORD_VALUE Value

# dont update if the ip has not changed
[ "$__RECORD_VALUE" = "$__IP" ] && {
    write_log 7 "DNS record is up to date"
    return 0
}

do_request "Action=UpdateDomainRecord" \
    "RR=$(encode_url_component "$__RR")" \
    "RecordId=$__RECORD_ID" \
    "Type=$__TYPE" \
    "Value=$(encode_url_component "$__IP")" || return 1

return 0

/usr/share/ddns/default/aliyun.com.json

{
    "name": "aliyun.com",
    "ipv4": {
        "url": "update_aliyun_com.sh"
    },
    "ipv6": {
        "url": "update_aliyun_com.sh"
    }
}

Docker

Config

OpenWrt docker 默认用的配置文件是 /tmp/dockerd/daemon.json,/tmp 目录是在内存中,修改重启路由器后就失效

该配置文件是 /etc/init.d/dockerd 根据 /etc/config/dockerd 自动生成的,需要关闭 iptables,不然映射的端口局域网内也无法访问

config globals 'globals'
        option data_root '/opt/docker/'
        option log_level 'warn'
        option iptables '0'
        option auto_start '1'
        list registry_mirrors 'https://mirror.xxxx.com'

Storage Driver

https://docs.docker.com/storage/storagedriver/select-storage-driver/

默认 Storage Driver 是 vfs,这玩意有个大坑,每一层镜像都会全量保存,而不是增量保存,就会特别占用磁盘空间,在 /etc/init.d/dockerd 里面看了一下读取配置的代码,并不能设置 Storage Driver,我的做法是直接在 /etc/init.d/dockerd 内部启动 dockerd 的时候直接加参数 --storage-driver=fuse-overlayfs,这个需要安装 fuse-overlayfs

如果 docker 的目录是挂载的其他分区,如ext4,推荐使用 overlay2