114 lines
3.1 KiB
Bash
114 lines
3.1 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# wg-convert-config — rewrite a WireGuard config's DNS= line as an equivalent
|
|
# PostUp command, for containers where openresolv/resolvconf can't run.
|
|
#
|
|
# usage: wg-convert-config <wg0.conf> [out.conf]
|
|
# wg-convert-config <wg0.conf> - # write to stdout
|
|
#
|
|
# With no output path, writes ./ctr<basename of input>.
|
|
|
|
set -euo pipefail
|
|
|
|
prog=${0##*/}
|
|
|
|
usage() {
|
|
cat >&2 <<EOF
|
|
usage: $prog <wg0.conf> [out.conf]
|
|
|
|
Moves DNS= out of [Interface] and appends an equivalent PostUp that writes
|
|
/etc/resolv.conf directly. Handles comma-separated addresses (v4 and v6) and
|
|
treats non-IP values as search domains. Use - as out.conf for stdout.
|
|
Defaults to ./ctr<input basename>.
|
|
EOF
|
|
exit "${1:-2}"
|
|
}
|
|
|
|
case ${1:-} in
|
|
-h | --help) usage 0 ;;
|
|
"" | -*) usage ;;
|
|
esac
|
|
(($# <= 2)) || usage
|
|
|
|
src=$1
|
|
dst=${2:-ctr${src##*/}}
|
|
|
|
[[ -r $src ]] || { printf '%s: cannot read %s\n' "$prog" "$src" >&2; exit 1; }
|
|
if [[ $dst != - && -e $dst && $src -ef $dst ]]; then
|
|
printf '%s: refusing to overwrite the source file\n' "$prog" >&2
|
|
exit 1
|
|
fi
|
|
|
|
convert() {
|
|
awk '
|
|
BEGIN { q = "\047" }
|
|
|
|
function flushpend( i) {
|
|
for (i = 1; i <= npend; i++) print pend[i]
|
|
npend = 0
|
|
}
|
|
|
|
function emit( i, out) {
|
|
if (!nns && !nsd) return
|
|
out = "PostUp = printf " q "%s\\n" q
|
|
for (i = 1; i <= nns; i++) out = out " " q "nameserver " ns[i] q
|
|
if (nsd) {
|
|
out = out " " q "search"
|
|
for (i = 1; i <= nsd; i++) out = out " " sd[i]
|
|
out = out q
|
|
}
|
|
print out " > /etc/resolv.conf"
|
|
if (nns > 3)
|
|
printf("%s: %d nameservers emitted; glibc reads only the first 3\n",
|
|
prog, nns) > "/dev/stderr"
|
|
nns = 0; nsd = 0
|
|
}
|
|
|
|
# Section header: close out the [Interface] block before leaving it.
|
|
/^[[:space:]]*\[/ {
|
|
if (iface) emit()
|
|
flushpend()
|
|
iface = (tolower($0) ~ /^[[:space:]]*\[interface\][[:space:]]*$/)
|
|
print
|
|
next
|
|
}
|
|
|
|
# DNS = a, b, c (keys are case-insensitive, # starts a comment)
|
|
iface && tolower($0) ~ /^[[:space:]]*dns[[:space:]]*=/ {
|
|
s = $0
|
|
sub(/#.*/, "", s)
|
|
sub(/^[^=]*=/, "", s)
|
|
gsub(/,/, " ", s)
|
|
n = split(s, a, /[[:space:]]+/)
|
|
for (i = 1; i <= n; i++) {
|
|
if (a[i] == "") continue
|
|
if (a[i] ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ ||
|
|
(a[i] ~ /:/ && a[i] ~ /^[0-9a-fA-F:.%]+$/))
|
|
ns[++nns] = a[i]
|
|
else
|
|
sd[++nsd] = a[i]
|
|
}
|
|
next
|
|
}
|
|
|
|
# Hold blank lines so the PostUp lands above them, not under [Peer].
|
|
iface && /^[[:space:]]*$/ { pend[++npend] = $0; next }
|
|
|
|
{ flushpend(); print }
|
|
|
|
END { if (iface) emit(); flushpend() }
|
|
' prog="$prog" "$src"
|
|
}
|
|
|
|
if [[ $dst == - ]]; then
|
|
convert
|
|
else
|
|
tmp=$(mktemp -- "$dst.XXXXXX")
|
|
trap 'rm -f -- "$tmp"' EXIT
|
|
convert > "$tmp"
|
|
chmod --reference="$src" -- "$tmp" 2>/dev/null || chmod 600 -- "$tmp"
|
|
mv -- "$tmp" "$dst"
|
|
trap - EXIT
|
|
printf '%s: wrote %s\n' "$prog" "$dst" >&2
|
|
fi
|