Script qui-fait-quoi.sh

Script qui-fait-quoi.sh

Notes

Outil ou script pour déterminer rapidement qui fait quoi dans un système linux kde plasma bureau ou portable avec vpn activé ou pas , wifi ou lan
Dns utilisé , accès ou au réseau local, domaine .arpa, etc…

Jqui-fait-quoi.sh, un script en lecture seule qui regroupe ces vérifications en une seule sortie.

Il affiche, section par section :

  • Connexion : interfaces actives avec leur type (wifi, ethernet, tunnel, bridge), profils NetworkManager actifs, routes par défaut.
  • VPN et tunnels : état de Mullvad, de Tailscale (avec le nœud de sortie s’il y en a un), WireGuard, et par quelle interface sort le trafic Internet.
  • DNS : où pointe /etc/resolv.conf (stub ou uplink), serveurs et domaines routés par interface (~home.arpa), et qui écoute sur le port 53.
  • Résolution : pour chaque nom testé, la réponse de resolvectl query avec l’interface et le serveur qui ont répondu, comparée à celle des applications (getent).
  • Accès local : route et ping vers l’IP du LAN et celle du tailnet, /health de cwwk, et le DoH dns.home.arpa.
  • Navigateurs : network.trr.* et network.lna.skip-domains de chaque profil Firefox ou LibreWolf, et les politiques Brave et Firefox présentes sur le disque.

Utilisation :

1
2
3
4
./qui-fait-quoi.sh                  # diagnostic complet
./qui-fait-quoi.sh -p               # + connexions établies par processus
./qui-fait-quoi.sh nas.home.arpa    # teste d'autres noms
sudo ./qui-fait-quoi.sh -p          # + tables nftables et processus des autres utilisateurs

Les noms et adresses de test sont en haut du fichier (NOMS_TEST, IP_LAN_TEST, IP_TAILNET_TEST, DOH_URL, HEALTH_URL), à adapter à ton réseau.

Quelques limites à garder en tête :

  • l’indication « sortie Internet » ignore les règles par marque de paquet que Mullvad utilise, donc elle peut montrer l’interface locale alors que le trafic part dans le tunnel ;
  • l’import de profils Flatpak ou Snap n’est pas couvert ;
  • si systemd-resolved n’est pas actif sur un poste, la section DNS le signale et la résolution passe seulement par getent.

Pour aller plus loin sans script, ces commandes reprennent chaque point à la main : resolvectl status, resolvectl query <nom>, ip route get <ip>, nmcli connection show --active et ss -tnp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env bash
# qui-fait-quoi.sh : état réseau d'un poste Linux (KDE Plasma, bureau ou portable)
#   connexion (wifi/LAN), VPN (Mullvad, Tailscale, WireGuard), DNS réellement utilisé,
#   accès au réseau local et au tailnet, domaine home.arpa, réglages des navigateurs.
# Lecture seule : ne modifie rien. Avec sudo, quelques détails de plus (nft, processus).
#
# Usage : ./qui-fait-quoi.sh [-p] [nom1 nom2 ...]
#   -p        ajoute le décompte des connexions établies par processus
#   nom...    noms à tester à la place de NOMS_TEST

# ---- À adapter à ton réseau ----
NOMS_TEST=(cwwk.home.arpa dns.home.arpa example.com)
IP_LAN_TEST=192.168.0.205
IP_TAILNET_TEST=100.64.0.2
DOH_URL=https://dns.home.arpa/dns-query
HEALTH_URL=https://cwwk.home.arpa/health
# --------------------------------

PROCS=0
while getopts "p" o; do
  case $o in p) PROCS=1 ;; *) exit 2 ;; esac
done
shift $((OPTIND - 1))
[ $# -gt 0 ] && NOMS_TEST=("$@")

t()    { printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; }
ok()   { printf '  \033[32m✔\033[0m %s\n' "$*"; }
ko()   { printf '  \033[31m✘\033[0m %s\n' "$*"; }
info() { printf '  • %s\n' "$*"; }
indent() { sed 's/^/      /'; }
have() { command -v "$1" >/dev/null 2>&1; }

have ip || { echo "iproute2 (commande ip) est requis" >&2; exit 1; }

dev_of_route() { awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}'; }

iface_type() {
  local d=$1
  if   [ -d "/sys/class/net/$d/wireless" ]; then echo "wifi"
  elif [ -d "/sys/class/net/$d/bridge" ];   then echo "bridge"
  elif [ -e "/sys/class/net/$d/tun_flags" ] || [ "$(cat "/sys/class/net/$d/type" 2>/dev/null)" = 65534 ]; then
    echo "tunnel (VPN, Tailscale, WireGuard)"
  else echo "ethernet/autre"; fi
}

# ---------------------------------------------------------------- Connexion
t "Connexion"
ip -br addr show up | while read -r d state addrs; do
  d=${d%%@*}
  [ "$d" = lo ] && continue
  info "$d [$(iface_type "$d")] $state $addrs"
done
if have nmcli; then
  nmcli -t -f NAME,TYPE,DEVICE connection show --active 2>/dev/null |
    while IFS=: read -r n ty dv; do info "NetworkManager : $n ($ty) sur ${dv:--}"; done
fi
info "routes par défaut :"
ip route show default | indent

# ---------------------------------------------------------------- VPN
t "VPN et tunnels"
if have mullvad; then info "Mullvad : $(mullvad status 2>&1 | head -n1)"; else info "Mullvad : non installé"; fi
if have tailscale; then
  if tailscale status >/dev/null 2>&1; then
    ok "Tailscale actif ($(tailscale ip -4 2>/dev/null | head -n1))"
    tailscale status 2>/dev/null | grep -i 'exit node' | head -n1 | indent
  else
    ko "Tailscale installé mais arrêté ou déconnecté"
  fi
else
  info "Tailscale : non installé"
fi
if have wg && [ -n "$(wg show interfaces 2>/dev/null)" ]; then info "WireGuard : $(wg show interfaces)"; fi
sortie=$(ip route get 1.1.1.1 2>/dev/null | dev_of_route)
info "sortie Internet (vers 1.1.1.1) : ${sortie:-?} [$(iface_type "${sortie:-lo}")] (indicatif, hors règles par marque de paquet)"
if [ "$EUID" -eq 0 ] && have nft; then
  info "tables nftables : $(nft list tables 2>/dev/null | awk '{print $2" "$3}' | paste -sd';' -)"
fi

# ---------------------------------------------------------------- DNS
t "DNS : qui résout"
resolv=$(readlink -f /etc/resolv.conf)
info "/etc/resolv.conf -> $resolv"
case $resolv in
  */stub-resolv.conf)          ok "mode stub : les applications passent par systemd-resolved (127.0.0.53)" ;;
  /run/systemd/resolve/resolv.conf) info "mode uplink : les applications contactent directement les serveurs listés" ;;
  *) info "fichier géré autrement (NetworkManager, manuel...)" ;;
esac
grep -E '^(nameserver|search)' /etc/resolv.conf | indent
if have resolvectl && systemctl is-active -q systemd-resolved; then
  info "systemd-resolved, par interface (serveurs, domaines routés ~ , route par défaut) :"
  resolvectl status --no-pager 2>/dev/null |
    grep -E '^(Global|Link )|Current DNS|DNS Servers|DNS Domain|Default Route' | indent
else
  ko "systemd-resolved inactif (ou resolvectl absent) : regarde plutôt NetworkManager ou le resolv.conf ci-dessus"
fi
info "qui écoute sur le port 53 :"
ss -lntup 2>/dev/null | awk 'NR==1 || $5 ~ /:53$/' | indent

t "Résolution : qui répond pour chaque nom"
for n in "${NOMS_TEST[@]}"; do
  if have resolvectl; then
    if out=$(resolvectl query "$n" 2>&1); then
      ok "$n"
      grep -vE '^$|authenticated' <<<"$out" | indent
    else
      ko "$n : échec resolvectl"
      head -n2 <<<"$out" | indent
    fi
  fi
  a=$(getent ahosts "$n" 2>/dev/null | awk 'NR==1{print $1}')
  [ -n "$a" ] && info "vu par les applications (glibc) : $a" || ko "$n : getent ne résout pas"
done

# ---------------------------------------------------------------- Réseau local
t "Accès au réseau local et au tailnet"
for ip in "$IP_LAN_TEST" "$IP_TAILNET_TEST"; do
  r=$(ip route get "$ip" 2>/dev/null | head -n1)
  info "route vers $ip : ${r:-aucune}"
  if ping -c1 -W1 "$ip" >/dev/null 2>&1; then ok "$ip répond au ping"; else ko "$ip ne répond pas au ping"; fi
done
code=$(curl -s -m4 -o /dev/null -w '%{http_code}' "$HEALTH_URL" 2>/dev/null)
[ "$code" = 200 ] && ok "$HEALTH_URL : 200" || ko "$HEALTH_URL : ${code:-pas de réponse}"
code=$(curl -s -m4 -o /dev/null -w '%{http_code}' -H 'accept: application/dns-message' \
  "$DOH_URL?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB" 2>/dev/null)
[ "$code" = 200 ] && ok "DoH joignable : $DOH_URL" || ko "DoH injoignable : $DOH_URL (${code:-pas de réponse})"

# ---------------------------------------------------------------- Navigateurs
t "Navigateurs : réglages DNS et permission réseau local"
for f in ~/.mozilla/firefox/*/prefs.js ~/.mozilla/firefox/*/user.js \
         ~/.librewolf/*/prefs.js ~/.librewolf/*/user.js \
         ~/.config/librewolf/*/prefs.js ~/.config/librewolf/*/user.js; do
  [ -f "$f" ] || continue
  vals=$(grep -E 'network\.(trr\.(mode|uri|custom_uri|excluded-domains)|lna\.skip-domains)' "$f" |
         sed -E 's/user_pref\("([^"]+)", *(.*)\);/\1 = \2/')
  if [ -n "$vals" ]; then info "$f"; indent <<<"$vals"; fi
done
for f in /etc/brave/policies/managed/*.json /etc/firefox/policies/policies.json \
         /usr/lib/firefox/distribution/policies.json; do
  [ -f "$f" ] && { info "politique : $f"; indent <"$f"; }
done
info "Brave : vérifier brave://policy ; Firefox : about:networking#dns et about:config (network.trr.mode)"

# ---------------------------------------------------------------- Processus
if [ "$PROCS" = 1 ]; then
  t "Connexions établies par processus (sudo pour voir les autres utilisateurs)"
  ss -tnp state established 2>/dev/null |
    awk 'NR>1{ if (match($0,/users:\(\("[^"]+"/)) print substr($0,RSTART+9,RLENGTH-10) }' |
    sort | uniq -c | sort -rn | head -n 15 | indent
fi