Files
fitme3070.pt/shared/platform-tools/bin/geo-relay-update.sh
T
andreandClaude Opus 5.5 0e8b53f620 feat(audit): platform-tools atualizado (12f26fd) e registo de auditoria ligado
- 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>
2026-09-25 07:28:13 +01:00

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"