Calendrier de l'Avent Défense contre la magie noire 2019 C'est l'article du 16e jour.
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.
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.
La seule façon de dépanner à partir de zéro est de trouver et de découvrir.
** 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!
** 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
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
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!
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.
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_conntrackou
nf_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]
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.
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
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)
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)
Les commandes et éléments utilisés cette fois sont les suivants.
--Processus, services