Je passe beaucoup de temps à surveiller, sécuriser et comprendre ce qui se passe sur mon réseau domestique. Entre la box Internet, les équipements exposés sans le vouloir et les scans permanents venus d’Internet, je me suis demandé un jour une chose toute simple : mon IP publique est-elle connue comme “bruyante” ou suspecte sur Internet ?
C’est à dire, des outils malveillants utilisent ils mon réseau (pc, NAS, routeur, HA, …) ??
C’est comme cela que je suis tombé sur GreyNoise, un service vraiment intéressant qui permet de savoir si une adresse IP fait partie du “bruit” d’Internet, c’est-à-dire si elle est observée dans des activités de scan, de sondage ou de trafic malveillant.
GreyNoise décrit justement son approche comme une manière de qualifier le bruit de fond d’Internet et de contextualiser une IP observée.
Et comme souvent avec moi, après quelques tests, je me suis dit : “Tiens, ce serait quand même pratique d’avoir ça directement dans Home Assistant”.
Au départ, je pensais faire quelque chose de très simple avec une requête HTTP classique. Sur le papier, cela semblait trivial. En pratique, la méthode la plus évidente n’a pas fonctionné chez moi comme je l’espérais. J’ai donc changé d’approche et je suis finalement parti sur un capteur en ligne de commande. Dans cet article, je te raconte tout cela pas à pas, comme je l’ai réellement mis en place chez moi, avec les cartes Lovelace pour l’affichage final.

🎯 Mon objectif
Mon objectif était simple : intégrer dans Home Assistant un capteur capable d’interroger GreyNoise pour connaître l’état de mon IP publique, puis afficher le résultat dans un dashboard clair et lisible.
L’idée n’était pas de transformer Home Assistant en centre de cybersécurité avancé, mais plutôt d’ajouter un petit indicateur de contexte.
Un coup d’œil rapide devait me permettre de savoir si mon IP était vue comme bénigne, inconnue, ou éventuellement liée à une activité plus suspecte.
GreyNoise expose précisément ce type d’information via son endpoint public de vérification.
Je voulais aussi quelque chose de compréhensible pour un débutant : un capteur, quelques attributs utiles, et de jolies cartes pour rendre tout cela lisible sans avoir à ouvrir un terminal et évidemment sans prendre d’abonnement de quoi que ce soit et sans m’enregistrer non.
🧠 GreyNoise, c’est quoi ?
Quand on découvre GreyNoise pour la première fois, on peut se demander à quoi cela sert exactement.
En version très simple, GreyNoise observe en permanence le bruit de fond d’Internet : les scans automatisés, les sondages d’adresses IP, les tentatives de connexion répétitives, tous ces comportements qu’on ne voit pas forcément à l’œil nu mais qui existent en permanence sur le réseau mondial.
GreyNoise présente justement son service comme un moyen de distinguer l’activité de fond du trafic réellement significatif.
L’intérêt de GreyNoise, c’est qu’il permet de contextualiser une adresse IP. En gros, on peut savoir si cette IP est connue comme participant à ce bruit Internet, si elle est considérée comme légitime, ou si elle n’est tout simplement pas connue de leurs systèmes. Leur service public de vérification renvoie ce contexte sous forme de JSON.
Quand j’ai compris cela, j’ai trouvé l’idée excellente pour la maison. On a souvent une box Internet, parfois des redirections de ports, un VPN, des équipements accessibles à distance, et on ne sait pas toujours comment notre IP est “vue” depuis l’extérieur.
Sans être un outil de sécurité complet, GreyNoise donne un indice intéressant.
🆓 Les outils gratuits GreyNoise

Ce que j’ai bien aimé, c’est qu’on peut déjà tester des choses gratuitement, sans rentrer tout de suite dans une intégration compliquée.
Le premier outil pratique, c’est leur page de vérification en ligne. On ouvre la page, et elle indique directement comment l’IP publique utilisée pour la navigation est vue par GreyNoise.
C’est très pratique pour faire un premier test rapide, sans rien installer.
L’autre point très intéressant, c’est qu’il existe une API simple à interroger. Et c’est précisément cette API que j’ai voulu exploiter dans Home Assistant. En ligne de commande, cela revient à faire une requête du type :
curl -s -H "Accept: application/json" https://check.labs.greynoise.io/api/v1/check
Chez moi, la réponse ressemblait à ceci :
{
"ip": "82.65.xxx.xxx",
"status": "not_found",
"classification": null,
"noise": false,
"common_business_services": false,
"trust_level": null,
"error": "ip not found"
}
Ce format correspond bien au fonctionnement documenté du service public GreyNoise, qui renvoie notamment l’IP, le statut, la classification, l’indicateur noise, l’indicateur common_business_services, le niveau de confiance et un éventuel message d’erreur.
Dit simplement : mon IP n’était pas connue par GreyNoise, ce qui est plutôt rassurant dans ce contexte.
🧪 Mon premier essai dans Home Assistant
Comme souvent, j’ai commencé par la solution qui me semblait la plus “propre” : utiliser un capteur REST dans Home Assistant.
Sur le principe, c’était logique. J’avais une URL HTTP qui renvoyait du JSON, donc je me suis dit qu’un capteur REST ferait parfaitement l’affaire. La documentation Home Assistant REST permet justement de définir une ressource HTTP, de lire le JSON avec value_template et de récupérer des champs comme attributs avec json_attributes.
Je pensais récupérer directement l’état et les attributs comme l’IP, la classification ou encore le niveau de confiance.
Sauf que chez moi, cette approche n’a pas fonctionné correctement. Le capteur restait dans un état inexploitable. Plutôt que de perdre du temps à m’acharner sur une méthode qui ne donnait pas un résultat stable dans mon installation, j’ai décidé de basculer sur une autre solution.
Et honnêtement, c’est souvent comme cela que ça se passe en domotique : on part avec une idée, puis on ajuste en fonction du réel.
⌨️ Pourquoi je suis parti sur command_line
J’ai finalement choisi de m’appuyer sur un capteur en ligne de commande. Ce n’est pas forcément la méthode la plus “élégante” sur le papier, mais dans mon cas elle a été bien plus fiable.
Le principe est simple : Home Assistant exécute une commande curl, récupère la réponse JSON, puis extrait l’état principal et plusieurs attributs. L’intégration command_line de Home Assistant prend justement en charge une commande shell, un value_template et des attributs JSON.
Autrement dit, je suis parti d’un test qui fonctionnait déjà dans mon terminal, puis je l’ai simplement transposé dans Home Assistant.
C’est souvent une bonne stratégie pour les débutants : quand quelque chose marche déjà à la main, il est plus facile de comprendre ensuite ce qui se passe dans Home Assistant.
⚙️ Configuration dans Home Assistant
Dans mon fichier configuration.yaml, j’ai commencé par inclure un fichier dédié pour mes capteurs en ligne de commande :
command_line: !include command_line.yaml
Ensuite, dans command_line.yaml, j’ai ajouté ce capteur :
- sensor:
name: "GreyNoise IP Check"
unique_id: greynoise_ip_check
icon: mdi:shield-search
command: 'curl -s -H "Accept: application/json" https://check.labs.greynoise.io/api/v1/check'
command_timeout: 20
scan_interval: 100800
value_template: "{{ value_json['status'] }}"
json_attributes:
- ip
- classification
- noise
- common_business_services
- trust_level
- error
Je vais détailler cela très simplement :
- command : c’est la commande réellement exécutée par Home Assistant.
- command_timeout : j’autorise ici jusqu’à 20 secondes avant abandon.
- scan_interval : c’est la fréquence d’exécution, en secondes. Ici j’ai choisi 100800 secondes, donc toutes les 28 heures.
- value_template : cela récupère la valeur principale du capteur, ici le champ
statusdu JSON. - json_attributes : cela permet de stocker d’autres champs utiles comme attributs du capteur.
Pourquoi 28 heures ? Tout simplement parce que je n’avais pas besoin d’interroger GreyNoise toutes les heures. Et je veux éviter 24h car beaucoup de capteurs sont sur 24, donc ce sera 28h aujourd’hui. Ce n’est pas une donnée qui change en permanence chez moi, donc je préfère une exécution espacée.
🧾 Ce que le capteur me remonte

Une fois le capteur opérationnel, je récupère un état principal et plusieurs attributs.
L’état principal est le champ status. Chez moi, par exemple, j’obtiens not_found. C’est cette valeur qui devient l’état du capteur dans Home Assistant. Le endpoint public GreyNoise renvoie bien ce champ de statut dans sa réponse JSON.
À côté de cela, j’ai plusieurs attributs utiles :
- ip : l’adresse IP publique détectée.
- classification : la classification éventuelle.
- noise : indique si l’IP est considérée comme faisant partie du bruit Internet.
- common_business_services : indique si l’IP est liée à des services d’entreprise connus.
- trust_level : un indicateur supplémentaire quand il est disponible.
- error : un message d’information, par exemple “ip not found”.
📊 Mes cartes Lovelace
Une fois le capteur créé, je voulais surtout un affichage agréable dans le dashboard. Je me suis donc fait une petite page dédiée avec plusieurs cartes pour tester les rendus.
J’ai utilisé à la fois Mushroom, Button Card et une carte Markdown. Cela m’a permis de comparer un style plus “sobre”, un style plus “visuel”, et un style plus “informatif”.
🍄 Carte Mushroom

La première carte que j’ai faite est une carte Mushroom basée sur le capteur réel :
type: custom:mushroom-template-card
entity: sensor.greynoise_ip_check
primary: >
{% set c = state_attr(entity, 'classification') %}
{% if c == 'malicious' %}
GreyNoise : activité malveillante
{% elif c == 'suspicious' %}
GreyNoise : activité suspecte
{% elif c == 'benign' %}
GreyNoise : service légitime
{% elif states(entity) in ['not_found', 'unknown', 'unavailable'] %}
GreyNoise : aucune activité connue
{% else %}
GreyNoise : {{ states(entity) }}
{% endif %}
secondary: >
{% set ip = state_attr(entity, 'ip') or 'IP inconnue' %}
{% set classif = state_attr(entity, 'classification') or 'aucune' %}
{% set noise = state_attr(entity, 'noise') %}
{% set cbs = state_attr(entity, 'common_business_services') %}
IP : {{ ip }} • Classification : {{ classif }} • Noise : {{ noise }} •
Services connus : {{ cbs }}
icon: >
{% set c = state_attr(entity, 'classification') %}
{% if c == 'malicious' %}
mdi:shield-alert
{% elif c == 'suspicious' %}
mdi:shield-search
{% elif c == 'benign' %}
mdi:shield-check
{% else %}
mdi:shield-check-outline
{% endif %}
icon_color: >
{% set c = state_attr(entity, 'classification') %}
{% if c == 'malicious' %}
red
{% elif c == 'suspicious' %}
orange
{% elif c == 'benign' %}
teal
{% else %}
green
{% endif %}
multiline_secondary: true
fill_container: true
tap_action:
action: more-info
J’aime beaucoup cette carte parce qu’elle est facile à lire. En un coup d’œil, je vois un message clair, une icône adaptée et une couleur cohérente.
🧪 Cartes fictives

Pour comparer les états visuellement, j’ai aussi créé quelques cartes purement fictives. Cela permet de voir à quoi ressembleraient les différents cas sans attendre qu’ils se produisent réellement.
type: vertical-stack
cards:
- type: custom:mushroom-template-card
primary: Fictif - malicious
secondary: "IP : 45.67.89.10 • malicious • noise: true"
icon: mdi:shield-alert
icon_color: red
multiline_secondary: true
- type: custom:mushroom-template-card
primary: Fictif - benign
secondary: "IP : 1.1.1.1 • benign • noise: false"
icon: mdi:shield-check
icon_color: teal
multiline_secondary: true
- type: custom:mushroom-template-card
primary: Fictif - not found
secondary: "IP : 82.65.100.200 • not_found • noise: false"
icon: mdi:shield-check-outline
icon_color: green
multiline_secondary: true
C’est tout bête, mais très utile quand on construit une interface : on peut choisir le style avant même d’avoir un cas réel.
🎨 Carte Button Card

Ensuite, j’ai voulu quelque chose de plus visuel, presque comme une carte d’alerte. J’ai donc utilisé Button Card.
type: custom:button-card
entity: sensor.greynoise_ip_check
name: |
[[[
const c = entity?.attributes?.classification;
if (c === 'malicious') return 'GreyNoise - activité malveillante';
if (c === 'suspicious') return 'GreyNoise - activité suspecte';
if (c === 'benign') return 'GreyNoise - service légitime';
return 'GreyNoise - aucune activité connue';
]]]
icon: |
[[[
const c = entity?.attributes?.classification;
if (c === 'malicious') return 'mdi:shield-alert';
if (c === 'suspicious') return 'mdi:shield-search';
if (c === 'benign') return 'mdi:shield-check';
return 'mdi:shield-check-outline';
]]]
show_state: true
state_display: |
[[[
return entity?.state || 'unknown';
]]]
label: |
[[[
const ip = entity?.attributes?.ip || 'IP inconnue';
const c = entity?.attributes?.classification || 'aucune';
const noise = entity?.attributes?.noise;
const cbs = entity?.attributes?.common_business_services;
return `IP ${ip} • ${c} • noise: ${noise} • common business: ${cbs}`;
]]]
show_label: true
tap_action:
action: more-info
styles:
card:
- padding: 18px
- border-radius: 20px
- color: white
- background: |
[[[
const c = entity?.attributes?.classification;
if (c === 'malicious') return 'linear-gradient(135deg, #b71c1c 0%, #e53935 100%)';
if (c === 'suspicious') return 'linear-gradient(135deg, #ef6c00 0%, #ffa726 100%)';
if (c === 'benign') return 'linear-gradient(135deg, #00695c 0%, #26a69a 100%)';
return 'linear-gradient(135deg, #2e7d32 0%, #66bb6a 100%)';
]]]
grid:
- grid-template-areas: "\"i n\" \"i s\" \"l l\""
- grid-template-columns: 60px 1fr
- grid-template-rows: min-content min-content min-content
icon:
- width: 42px
- color: white
name:
- justify-self: start
- font-size: 18px
- font-weight: 700
state:
- justify-self: start
- font-size: 15px
- font-weight: 500
label:
- justify-self: center
- text-align: center
- width: 100%
- font-size: 13px
- opacity: 0.92
Cette carte est très sympa, surtout quand on veut quelque chose qui attire un peu plus l’œil. J’ai d’ailleurs ajusté la ligne du bas pour qu’elle soit centrée, ce qui améliore vraiment le rendu.
📝 Carte Markdown récapitulative

Enfin, j’ai ajouté une carte Markdown pour afficher toutes les informations de manière lisible :
type: markdown
content: >-
{% set e = 'sensor.greynoise_ip_check' %}
## Rapport complet GreyNoise
- **État** : {{ states(e) }}
- **IP** : {{ state_attr(e, 'ip') or 'inconnue' }}
- **Classification** : {{ state_attr(e, 'classification') or 'aucune' }}
- **Bruit Internet** : {{ state_attr(e, 'noise') }}
- **Services connus** : {{ state_attr(e, 'common_business_services') }}
- **Niveau de confiance** : {{ state_attr(e, 'trust_level') or '--' }}
- **Message d'information** : {{ state_attr(e, 'error') or 'aucun' }}
---
- **Dernière exécution de la requête** : {{
relative_time(states[e].last_updated) }}
- **Horodatage de la dernière exécution** : {{
as_local(states[e].last_updated).strftime('%d/%m/%Y %H:%M:%S') }}
J’aime bien cette carte parce qu’elle est très claire, surtout pour du diagnostic.
En plus, j’y ai ajouté la notion de temps écoulé depuis la dernière mise à jour, ce qui est pratique pour savoir quand la requête a été réellement exécutée.
Les propriétés last_updated et last_changed sont bien disponibles dans le moteur de templates Home Assistant pour ce type d’usage.
🧩 Ce que j’ai retenu de cette intégration
Ce petit projet m’a rappelé quelque chose d’important : en domotique, le plus important n’est pas toujours la méthode théoriquement la plus élégante, mais celle qui fonctionne réellement chez soi de manière fiable.
Au départ, je voulais partir sur du REST. Finalement, c’est le capteur en ligne de commande qui m’a permis d’obtenir un résultat stable, lisible et facile à maintenir. Et franchement, pour un usage domestique, c’est exactement ce que je cherchais.
J’ai aussi réalisé que ce type d’intégration a une vraie valeur pédagogique. On apprend à récupérer du JSON, à créer un capteur Home Assistant, à exploiter des attributs, à mettre en forme un dashboard, et à transformer une information brute en quelque chose de visuel et compréhensible.
Au final, j’ai utilisé la Carte Mushroom dans un petit coin de mon dashboard, d’un coup d’oeil, je verrai si l’icone passe en rouge.
Si le coeur m’en dit, je pourrai ajouter le changement d’état de sensor.greynoise_ip_check dans les déclencheurs d’éventuelles notifications par SMS ou visuelles…
✅ Conclusion
Avec GreyNoise, j’ai ajouté dans Home Assistant une petite brique de contexte réseau que je trouve vraiment intéressante. Ce n’est pas un outil miracle, ni un IDS complet, mais c’est un bon indicateur pour savoir comment mon IP publique est perçue depuis l’extérieur.
J’ai commencé par tester la page de vérification en ligne, puis la requête API en terminal, puis j’ai essayé l’intégration dans Home Assistant. Le capteur REST ne s’étant pas montré concluant dans mon cas, je suis parti sur command_line, et c’est finalement cette méthode qui a fait le job. L’approche décrite est cohérente avec les capacités documentées des intégrations REST et command_line de Home Assistant.
Au final, j’obtiens un capteur simple, quelques attributs utiles, et surtout des cartes Lovelace agréables à lire. Pour moi, c’est exactement le genre d’intégration que j’aime : un sujet un peu technique au départ, mais transformé en quelque chose de concret, visuel et accessible au quotidien.
