- shared/platform-tools: ea3616a → 12f26fd (27 commits). Traz o módulo de audit (f761d99, o pin da frota), «manter sessão iniciada», o registo de segurança da frota (o gancho que o login já tinha passa a funcionar) e a correção do IP do cliente encontrada nesta auditoria (último X-Forwarded-For / X-Real-IP), promovida ao partilhado. client_ip() da app delega nele. - config/functions_audit.php: audit() sobre platform_audit(); tabela audit_log criada no primeiro uso, segredos ocultados, nunca parte a ação. - Registado: login, falha de login, bloqueio por excesso de tentativas, logout, pedidos de recuperação, mudança/definição de palavra-passe, registo e criação de utilizadores, convites, perfil (antes/depois), todas as definições (db_update_setting, com valor anterior), cada passo da lixeira (apagar, restaurar, eliminar de vez) e ações nas mensagens. - Sistema → Auditoria (views/sysadmin/audit.php), só sysadmin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
4.0 KiB
Bash
101 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Refresh the iCloud Private Relay egress ranges that functions_geo.php reads.
|
|
#
|
|
# geo-relay-update.sh pt # one or more ISO country codes
|
|
# geo-relay-update.sh # falls back to $GEO_ALLOW_COUNTRIES
|
|
#
|
|
# Why this exists: Private Relay sends Safari traffic out through Apple's egress
|
|
# addresses, which are registered where Apple registered them and not where the
|
|
# person is. Against the ipdeny lists a subscriber in Aveiro looks foreign, gets
|
|
# refused, and never hears back. Apple publishes which country each egress range
|
|
# serves, so the gate can ask the right question about it.
|
|
#
|
|
# It writes relay-<cc>.v4 / relay-<cc>.v6 — same format as the ipdeny lists, read
|
|
# by the same code. **Only the countries you ask for**, and that is the point:
|
|
# the published list is 42k IPv4 ranges and 246k IPv6 (855 KB and 6.7 MB), while
|
|
# Portugal is 611 of them. The whole file would be a 6.7 MB commit every week and
|
|
# a 6.7 MB parse on every request, to answer a question about one country.
|
|
#
|
|
# Keeping it per-country is also what stops this becoming a Relay whitelist: a
|
|
# range serving France is simply never written, so a French relay user is
|
|
# refused by the normal path exactly like any other foreign address.
|
|
#
|
|
# Apple adds ranges as it adds capacity, so weekly is reasonable:
|
|
#
|
|
# 23 4 * * 1 /srv/sites/<site>/shared/platform-tools/bin/geo-relay-update.sh pt
|
|
#
|
|
# The files are committed, same as the ipdeny data and for the same reason: a
|
|
# deploy on a box that cannot reach Apple still has working data — as current as
|
|
# the last commit.
|
|
|
|
set -euo pipefail
|
|
|
|
DATA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/data/geo"
|
|
URL="${ICLOUD_RELAY_URL:-https://mask-api.icloud.com/egress-ip-ranges.csv}"
|
|
|
|
# Apple serves relay capacity for a country from at least a few dozen ranges.
|
|
# Fewer than this means the country code was wrong, the format changed, or the
|
|
# download was truncated — and overwriting a good file with it would quietly
|
|
# turn every relay visitor back into a foreigner.
|
|
MIN_ROWS=10
|
|
|
|
countries=("$@")
|
|
if [ ${#countries[@]} -eq 0 ]; then
|
|
read -r -a countries <<< "${GEO_ALLOW_COUNTRIES//[,;]/ }"
|
|
fi
|
|
if [ ${#countries[@]} -eq 0 ]; then
|
|
echo "uso: $(basename "$0") <cc> [cc...] (ou defina GEO_ALLOW_COUNTRIES)" >&2
|
|
exit 2
|
|
fi
|
|
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
|
|
echo "iCloud Private Relay: a descarregar $URL"
|
|
if ! curl -fsS --max-time 60 "$URL" -o "$tmp/raw.csv"; then
|
|
echo "FALHOU o download — os ficheiros anteriores mantêm-se." >&2
|
|
exit 1
|
|
fi
|
|
|
|
failed=0
|
|
for cc in "${countries[@]}"; do
|
|
cc="$(echo "$cc" | tr '[:upper:]' '[:lower:]')"
|
|
[ -n "$cc" ] || continue
|
|
up="$(echo "$cc" | tr '[:lower:]' '[:upper:]')"
|
|
|
|
# O formato da Apple é: cidr,countryCode,region,city, — só as duas
|
|
# primeiras colunas interessam, e uma linha que não seja exactamente isso é
|
|
# descartada em vez de adivinhada: uma mudança de formato tem de aparecer
|
|
# como "poucas gamas" e parar o script, não como um ficheiro meio lido.
|
|
awk -F',' -v want="$up" '
|
|
$1 ~ /\// && toupper($2) == want {
|
|
if ($1 ~ /:/) { print $1 > v6 } else { print $1 > v4 }
|
|
}
|
|
' v4="$tmp/$cc.v4" v6="$tmp/$cc.v6" "$tmp/raw.csv" || true
|
|
touch "$tmp/$cc.v4" "$tmp/$cc.v6"
|
|
|
|
rows4=$(wc -l < "$tmp/$cc.v4" | tr -d ' ')
|
|
rows6=$(wc -l < "$tmp/$cc.v6" | tr -d ' ')
|
|
total=$((rows4 + rows6))
|
|
|
|
if [ "$total" -lt "$MIN_ROWS" ]; then
|
|
echo "FALHOU $up: só $total gamas (mínimo $MIN_ROWS). Ficheiros anteriores mantidos." >&2
|
|
failed=1
|
|
continue
|
|
fi
|
|
|
|
# Ordenados no disco para um git diff entre duas actualizações se conseguir
|
|
# ler. O módulo volta a ordená-los ao carregar, porque esta ordem é textual
|
|
# e a procura precisa da ordem dos bytes empacotados.
|
|
sort -u "$tmp/$cc.v4" -o "$tmp/$cc.v4"
|
|
sort -u "$tmp/$cc.v6" -o "$tmp/$cc.v6"
|
|
|
|
mkdir -p "$DATA_DIR"
|
|
mv "$tmp/$cc.v4" "$DATA_DIR/relay-$cc.v4"
|
|
mv "$tmp/$cc.v6" "$DATA_DIR/relay-$cc.v6"
|
|
echo "OK $up: $rows4 gamas IPv4, $rows6 IPv6 → $DATA_DIR/relay-$cc.{v4,v6}"
|
|
done
|
|
|
|
exit "$failed"
|