Techniques de dépannage de (presque) rien

Calendrier de l'Avent Défense contre la magie noire 2019 C'est l'article du 16e jour.

introduction

Dans certains cas, la difficulté de dépannage augmente involontairement en raison de la progression de l'automatisation du déploiement, de la virtualisation de type conteneur et des microservices.

Dans ce numéro, nous verrons comment procéder au dépannage ** dans ces cas, même si vous ne connaissez pas le système cible.

début

Vous avez obtenu les informations requises pour la connexion SSH au serveur Linux et la connexion a réussi. Il est possible de basculer vers l'utilisateur root. Mais ** je ne sais rien d'autre que les informations de connexion **.

typewriter@server:~ $ sudo su -
root@server:~ # eixt
-bash: eixt: command not found
root@server:~ # exit
logout
typewriter@server:~ $

Pendant ce temps, j'ai reçu un e-mail de demande ambigu disant "L'accès à une page Web provoque une erreur" et on me demande de répondre.

Allons-nous en.

Techniques de dépannage

La seule façon de dépanner à partir de zéro est de trouver et de découvrir.

Trouvez une application

** ps ** (Ni docker ps ni pstree ne sont utilisés)

Vous pouvez également effectuer une recherche à l'aide de la commande top pour afficher les processus en cours d'exécution (s'il y a beaucoup de processus, ).

##Afficher tous les processus au format BSD / format orienté utilisateur
$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      3052  3.2 19.0 1122908 89636 ?       Ssl  02:24   0:03 /usr/bin/dockerd --default-ulimit nofile=1024:4096
root      3086  0.4  4.5 1004052 21332 ?       Ssl  02:24   0:00 docker-containerd --config /var/run/docker/containerd/containerd.toml
root      3865  0.0  1.1  10632  5332 ?        Ss   02:25   0:00 nginx: master process nginx -g daemon off;
101       3914  0.0  0.5  11088  2588 ?        S    02:25   0:00 nginx: worker process

Nginx est peut-être en cours d'exécution sur le conteneur Docker. Allons vérifier.

La meilleure façon de vérifier est d'utiliser docker ps ou docker top CONTAINER. Cependant, il est également possible d'afficher l'arborescence des processus avec l'option f ( --forest) de la commande ps et de la vérifier à partir de la relation parent-enfant.

##Arborescence de tous les processus au format BSD et au format orienté utilisateur
$ ps auxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      3052  0.4 16.7 1122908 78684 ?       Ssl  02:24   0:05 /usr/bin/dockerd --default-ulimit nofile=1024:4096
root      3086  0.4  4.8 1005108 22660 ?       Ssl  02:24   0:04  \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
root      3829  0.0  0.8   7512  4184 ?        Sl   02:25   0:00  |   \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/contain
root      3865  0.0  1.1  10632  5332 ?        Ss   02:25   0:00  |       \_ nginx: master process nginx -g daemon off;
101       3914  0.0  0.5  11088  2588 ?        S    02:25   0:00  |           \_ nginx: worker process

Il fonctionne sur Docker!

Rechercher les fichiers de configuration et les fichiers journaux

** Descripteur de fichier **

Sous Linux (POSIX), chaque processus a une liste de descripteurs de fichiers, ou en bref, une "liste de fichiers ouverts". Cela peut être vu à travers procfs (bien que dans la plupart des cas, le même utilisateur que le processus de démarrage). Doit être).

Jetons un œil au descripteur de fichier du processus nginx.

$ sudo ls -l /proc/3865/fd
total 0
lr-x------ 1 root root 64 Dec 15 02:25 0 -> 'pipe:[16216]'
l-wx------ 1 root root 64 Dec 15 02:25 1 -> 'pipe:[16217]'
l-wx------ 1 root root 64 Dec 15 02:25 2 -> 'pipe:[16218]'
lrwx------ 1 root root 64 Dec 15 02:25 4 -> 'socket:[75443]'
lrwx------ 1 root root 64 Dec 15 02:25 5 -> 'socket:[75444]'
lrwx------ 1 root root 64 Dec 15 02:25 6 -> 'socket:[16370]'

Je ne pouvais pas obtenir de fichiers avec juste des tubes et des sockets (à part, Linux permet aux tubes et aux sockets d'être traités comme des fichiers spéciaux).

Mais n'abandonnez pas. [Le descripteur de fichier du processus est déterminé comme étant «0» comme entrée standard (stdin), «1» comme sortie standard (stdout) et «2» comme sortie d'erreur standard (stderr)](https: //linuxjm.osdn. Depuis jp / html / LDP_man-pages / man3 / stdin.3.html # lbAD), essayons de sucer la sortie standard avec cat.

$ sudo cat /proc/3865/fd/1
##(Accédez à la page Web ici)
xxx.xx.xxx.xxx - - [15/Dec/2019:06:03:51 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" "-"
## ( Ctrl+Arrêtez de sucer avec la touche C)
^C
$ 

Le journal d'accès de nginx est sorti. Cracher des bûches sur une sortie standard est une manière orthodoxe de faire fonctionner un conteneur.

S'il est imprimé dans un fichier, vous devriez voir le chemin comme suit:

$ sudo ls -l /proc/11178/fd
Total 0
lrwx------1 racine racine 64 15 décembre 14:35 0 -> /dev/null
lrwx------1 racine racine 64 15 décembre 14:35 1 -> /dev/null
l-wx------1 racine racine 64 15 décembre 14:35 2 -> /var/log/nginx/error.log
l-wx------1 racine racine 64 15 décembre 14:35 44 -> /var/log/nginx/access.log

strace,kill

L'emplacement du fichier de configuration n'est pas encore connu. Puisqu'il s'agit de nginx, il est * presque * sûr que c'est / etc / nginx /, mais faisons semblant de ne pas le savoir.

La commande strace peut surveiller les appels et les signaux système. Les appels système incluent également la lecture et l'écriture de fichiers.

$ sudo strace -t -p 3865
strace: Process 3865 attached
05:36:54 rt_sigsuspend([], 8)           = ? ERESTARTNOHAND (To be restarted if no handler)

La surveillance a commencé (terminer par Ctrl + C). Dans cet état, laissez nginx lire le fichier de configuration.

nginx recharge le fichier de configuration lorsqu'il reçoit le signal HUP. Apache est un signal ʻUSR1`, et d'autres applications peuvent être capables de recharger avec un signal spécifique.

HUP changing configuration, keeping up with a changed time zone (only for FreeBSD and Linux), starting new worker processes with a new configuration, graceful shutdown of old worker processes

Controlling nginx

Vous pouvez envoyer un signal HUP avec une commande bruyante appelée la commande kill.

$ sudo kill -HUP 3865
05:37:25 --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=53, si_uid=0} ---
05:37:25 rt_sigreturn({mask=[HUP INT QUIT USR1 USR2 ALRM TERM CHLD WINCH IO]}) = -1 EINTR (Interrupted system call)
05:37:25 stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=127, ...}) = 0
05:37:25 uname({sysname="Linux", nodename="1b01e2a57209", ...}) = 0
05:37:25 openat(AT_FDCWD, "/etc/nginx/nginx.conf", O_RDONLY) = 8
05:37:25 fstat(8, {st_mode=S_IFREG|0644, st_size=643, ...}) = 0

Il y avait un mouvement dans le terminal que je surveillais avec strace. L'accent est mis sur l'appel système ʻopenat. Vous pouvez voir que vous avez ouvert le fichier / etc / nginx / nginx.conf`.

Je connais l'emplacement du fichier de configuration. Toutes nos félicitations!

Trouver un autre serveur

C'est un peu ennuyeux quand le problème est susceptible d'être sur un autre serveur. Vous pouvez vérifier les paramètres de proxy inverse de nginx, ou vous pouvez être en mesure de trouver d'autres serveurs par les méthodes suivantes.

arp,arp-scan

Je n'entrerai pas dans les détails, mais les hôtes du même sous-réseau peuvent être trouvés par analyse ARP. Si le contenu du cache ne vous dérange pas, vous pouvez le vérifier avec la commande ʻarp`.

##Vérifiez le contenu du cache
$ arp -a
ip-172-31-16-1.ap-northeast-1.compute.internal (172.31.16.1) at 06:d0:4e:xx:xx:xx [ether] on eth0

##Balayage ARP (arp-La commande scan doit être installée séparément)
###Calculer la plage (sous-zone) de l'analyse ARP
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 172.31.24.219  netmask 255.255.240.0  broadcast 172.31.31.255
###Sous-zone d'en haut(Adresse réseau/CIDR)Est 172.31.16.0/20
$ sudo arp-scan 172.31.16.0/20
Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9.2 with 4096 hosts (http://www.nta-monitor.com/tools-resources/security-tools/arp-scan/)
172.31.16.1 06:d0:4e:xx:xx:xx (Unknown)
172.31.26.132 06:4e:7e:xx:xx:xx (Unknown)
172.31.29.38  06:8b:fe:xx:xx:xx (Unknown)

netstat,iptables(ip_conntrack),nftables(nf_conntrack)

Vous pouvez utiliser la commande netstat pour voir quelles connexions TCP et quels ports TCP / UDP écoutent.

$ sudo netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3214/sshd
tcp        0      0 172.31.24.219:22        xxx.xx.xxx.xxx:58168    ESTABLISHED 32051/sshd: USERNAME
tcp6       0      0 :::22                   :::*                    LISTEN      3214/sshd
tcp6       0      0 :::80                   :::*                    LISTEN      3003/docker-proxy

C'est le résultat de l'exécution sur le serveur (en dehors du conteneur) où nginx a été démarré plus tôt. Je ne ressens aucun signe de nginx, mais c'est normal. En effet, la communication avec le conteneur Docker est NAT par iptables (nftables).

Si vous vous dépêchez et faites netstat à l'intérieur du conteneur, vous pouvez obtenir command not found. Mais calme-toi. Vérifions de l'extérieur du conteneur.

Vous pouvez vérifier les paramètres NAT avec la commande ʻiptables`.

$ sudo iptables -L
Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER     all  --  anywhere             anywhere

Chain DOCKER (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             ip-172-17-0-2.ap-northeast-1.compute.internal  tcp dpt:http

Et les connexions TCP NAT par iptables / nftables peuvent être trouvées dans procfs depuis ʻip_conntrackounf_conntrack`.

$ sudo cat /proc/net/nf_conntrack
ipv4     2 tcp      6 431997 ESTABLISHED src=xxx.xx.xxx.xxx dst=172.31.24.219 sport=57245 dport=80 src=172.17.0.2 dst=xxx.xx.xxx.xxx sport=80 dport=57245 [ASSURED] mark=0 zone=0 use=2
ipv4     2 tcp      6 103 TIME_WAIT src=172.17.0.2 dst=xx.xx.xx.xxx sport=46684 dport=8080 src=xx.xx.xx.xxx dst=172.31.24.219 sport=8080 dport=46684 [ASSURED] mark=0 zone=0 use=2

La première ligne est la connexion où l'accès au port TCP 80 est NATé au conteneur Docker. La deuxième ligne est le NAT de la connexion depuis l'intérieur du conteneur Docker vers le port TCP 8080 sur l'hôte externe.

À partir de la deuxième ligne, nous pouvons déduire que nginx peut être un proxy inverse vers un hôte externe.

** Depuis une console telle qu'AWS ou GCP ** (système d'équilibrage de charge)

Si la destination de communication trouvée est un équilibreur de charge, l'existence du serveur au-delà ne peut pas être recherchée. Malheureusement, je n'ai pas d'autre choix que de regarder les paramètres de l'équilibreur de route.

** De l'historique des commandes de chacun **

Si vous pensez que "quelqu'un doit le faire", créez un précédent. L'historique des commandes sorti par la commande history est enregistré dans .bash_history pour bash.

$ sudo cat /home/*/.bash_history | grep ssh
ssh -p 11122 example.com
ssh [email protected]

Regardez de plus près le serveur

Si vous arrivez sur un serveur suspect, vérifiez-le. En plus des commandes expliquées jusqu'à présent, les commandes et éléments suivants peuvent également être utilisés.

procfs

En plus des descripteurs de fichiers et des sessions NAT, le système de fichiers proc peut acquérir diverses informations telles que des chaînes de commande au démarrage, y compris des paramètres.

En plus de la page de manuel procfs, linux procfs introduction approfondie --SIer mais je veux faire un blog technologique peut être confirmé avec un exemple de sortie.

/var/log/{syslog,messages}

Récupéré par syslogd (rsyslogd) Divers journaux du système modifié sont générés. Bien que ce soit rare, un enregistrement est enregistré lorsque OOM Killer qui tue un processus lorsque la mémoire est insuffisante est activé (The OOM CTF pour OOM Killer). Et [Out Of Memory Management](voir https://www.kernel.org/doc/gorman/html/understand/understand016.html).

Dec 15 10:51:07 ip-172-31-24-219 kernel: Out of memory: Kill process 6359 (bash) score 635 or sacrifice child
Dec 15 10:51:07 ip-172-31-24-219 kernel: Killed process 6360 (yes) total-vm:114636kB, anon-rss:88kB, file-rss:0kB, shmem-rss:0kB
Dec 15 10:51:07 ip-172-31-24-219 kernel: oom_reaper: reaped process 6360 (yes), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

free,top,vmstat,ps

Bien qu'il se chevauche partiellement, il s'agit d'un groupe de commandes majeur qui génère la mémoire, le processeur, les E / S et d'autres informations. Je ne vais pas l'expliquer, mais il convient de rappeler que vous pouvez également afficher LWP (threads) avec ps -L.

## PID:Numéro de processus, LWP: LWP(fil)ID, NLWP: LWP(fil)nombre
$ ps -efL
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
root      3564     1  3564  0    8 02:24 ?        00:00:00 /usr/libexec/amazon-ecs-init start
root      3564     1  3567  0    8 02:24 ?        00:00:00 /usr/libexec/amazon-ecs-init start
root      3564     1  3568  0    8 02:24 ?        00:00:00 /usr/libexec/amazon-ecs-init start
(réduction)

objectif

Avec la méthode décrite jusqu'à présent, vous pouvez désormais rechercher des serveurs, des applications, des paramètres, des fichiers journaux et voir à quoi ressemble le serveur.

Vous serez en mesure de répondre à des demandes telles que "L'accès à une page Web provoque une erreur".

unicorn_err.log:E, [2019-12-15T21:18:43.339882 #10627] ERROR -- : worker=4 PID:14246 timeout (98s > 60s), killing
unicorn_err.log:E, [2019-12-15T21:18:43.339910 #10627] ERROR -- : worker=5 PID:14254 timeout (80s > 60s), killing

Wow, le traitement prend plus de 60 secondes! ??

(ne continue pas)

Résumé

Les commandes et éléments utilisés cette fois sont les suivants.

--Processus, services

Recommended Posts

Techniques de dépannage de (presque) rien
Keras à partir de rien
Keras à partir de rien 5ème
Keras à partir de rien 1er
Keras à partir de rien 4e
Keras à partir de rien 2e
Keras à partir de rien 3e