2011-06-25 3 views
10

Pour respecter la vie privée de mes utilisateurs, j'essaie d'anonymiser leurs adresses IP dans les fichiers journaux nginx.Anonymize IP se connectant à nginx?

Une façon de le faire serait de définir un format de journal personnalisé, comme ceci:

log_format noip '127.0.0.1 - [$time_local] ' 
    '"$request" $status $body_bytes_sent ' 
    '"$http_referer" "$http_user_agent" $request_time'; 

Cette méthode a deux inconvénients: Je ne peux pas distinguer entre deux utilisateurs et ne peut pas utiliser des outils géo de localisation. La meilleure chose serait de raccourcir l'adresse IP (87.12.23.55 deviendrait 87.12.23.1).

Y a-t-il une possibilité d'y parvenir en utilisant nginx config scripting?

Merci.

+0

connexes (apache): http://serverfault.com/q/343031/75968 – cweiske

Répondre

13

Même s'il existe déjà une réponse acceptée, la solution semble ne pas être valide.

nginx a la directive log_format, qui a un contexte de http. Cela signifie que le log_format ne peut être (valide) que dans la section http {} du fichier de configuration, PAS dans les sections du serveur!

D'autre part, nous avons une si directive, qui a un contexte du serveur et l'emplacement.

nous ne pouvons pas utiliser « si » et « log_format » dans une section de serveur (ce qui est fait dans la solution retenue)

Ainsi, le si n'est pas utile ici, aussi si le mal (http://wiki.nginx.org/IfIsEvil)! Nous avons besoin de quelque chose qui travaille à contexte http parce que là, le log_format peut être définie d'une manière valable, et c'est le seul endroit en dehors du contexte du serveur, où nos hôtes virtuels sont définis ...

Heureusement, il y a une fonction carte dans nginx! map remappe certaines valeurs en nouvelles valeurs (accessibles dans les variables qui peuvent être utilisées dans une directive log_format). Et le bon message: Cela fonctionne aussi avec des expressions régulières.

Mettons donc nos adresses IPv4 et IPv6 en adresses anonymisées. Cela doit être fait en 3 étapes, car la carte ne peut pas accumuler les valeurs retournées, elle peut seulement renvoyer des chaînes ou des variables, pas une combinaison des deux. Donc, au début, nous récupérons la partie d'IP que nous voulons avoir dans les fichiers de log, la seconde carte renvoie la partie qui symbolise la partie anonymisée, et la troisième règle de carte les assemble à nouveau.

Voici les règles qui vont dans le contexte http {}:

map $remote_addr $ip_anonym1 { 
default 0.0.0; 
"~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" $ip; 
"~(?P<ip>[^:]+:[^:]+):" $ip; 
} 

map $remote_addr $ip_anonym2 { 
default .0; 
"~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" .0; 
"~(?P<ip>[^:]+:[^:]+):" ::; 
} 

map $ip_anonym1$ip_anonym2 $ip_anonymized { 
default 0.0.0.0; 
"~(?P<ip>.*)" $ip; 
} 

log_format anonymized '$ip_anonymized - $remote_user [$time_local] ' 
    '"$request" $status $body_bytes_sent ' 
    '"$http_referer" "$http_user_agent"'; 

access_log /var/log/nginx/access.log anonymized; 

Après avoir ajouté ceci à votre fichier de configuration nginx.conf, souvenez-vous de recharger votre nginx. Vos fichiers journaux doivent maintenant contenir des adresses IP anonymes, si vous utilisez le format de journal "anonymisé" (c'est le paramètre de format de la directive access_log).

+1

Merci! J'ai changé la réponse acceptée à la vôtre. – endzeit

+1

Excellente réponse – mate64

+0

Est-il possible d'anonymiser le journal des erreurs avec un log_format personnalisé? Ou peut seulement le journal d'accès? – tschale

0

Je pense qu'une bonne solution pratique est d'anonymiser l'adresse IP avant de faire tourner vos fichiers journaux (ce que vous devriez faire tous les jours). Il y a beaucoup de scripts pour cette tâche disponibles pour Apache, et puisque le format de journal est au moins très similaire, ils devraient fonctionner hors de la boîte ou être facilement ajustables. Bien sûr, vous stockez toujours l'adresse IP complète pendant 24 heures ou moins, mais c'est mieux que de les laisser traîner pendant des années.

+3

Il est illégal de stocker des adresses IP en Allemagne. – mate64

1

Vous pouvez utiliser une instruction if avec des expressions régulières dans le bloc de serveur pour anonymiser les adresses IP sans aucun module perl ou lua supplémentaire.

intérieur nginx.conf

server { 
    if ($remote_addr ~ (\d+).(\d+).(\d+).(\d+)) { 
     set $ip_anym $1.$2.0.1; 
    } 
    log_format main '[$time_local] $ip_anym "$request" $status $body_bytes_sent $request_time "$http_referer" "$http_user_agent"';  

    access_log /var/log/access.log main; 
    .... 
} 

Nous l'IP et anonymes les affecter à une nouvelle variable appelée $ ip_anym que nous pouvons utiliser dans le format de journal au lieu du remote_addr original $. Dans l'exemple ci-dessus, nous conservons la première et la deuxième partie de l'adresse IP, vous pouvez également utiliser $ 1. $ 2. $ 3.1 si vous préférez ne remplacer que la dernière partie de l'ip.

+1

log_format n'est pas autorisé dans le contexte du serveur (vous recevez également un avertissement pour l'utiliser ici). Une solution possible est d'utiliser "map" et "log_format" dans le contexte http. Voir la solution sur http://www.mbr-is.com/central-anonymized-ip-addresses-for-nginx-for-all-virtual-hosts/ –

3

La réponse acceptée semble un peu gonflée. La version actuelle de nginx vous permet de le faire de cette façon:

map $remote_addr $remote_addr_anon { 
    ~(?P<ip>\d+\.\d+\.\d+)\. $ip.0; 
    ~(?P<ip>[^:]+:[^:]+):  $ip::; 
    default      0.0.0.0; 
}