- 投稿日:2020-12-15T23:57:24+09:00
Linuxの代表的なコマンド(7つ)
①cd [path](current directory)
[path]に移動するためのコマンド。②pwd(print working directory)
今いるディレクトリを表示させるコマンド。③mkdir [new folder](make directory)
新しいフォルダを作成するためのコマンド。④touch [new file]
新しいファイルを作成するためのコマンド。⑤ls(list)
カレントディレクトリのファイル、フォルダを一覧表示させるためのコマンド。⑥rm [file]
既存のファイルを削除するためのコマンド。⑦rm -r [folder]
既存のフォルダの削除するためのコマンド。
- 投稿日:2020-12-15T22:52:20+09:00
Linux カーネルについて概要をざっと理解する
Linux カーネルについて全く知識がなかったので、これ一冊で完全理解 Linuxカーネル超入門 という本を参考に概要をまとめてみようと思います。
Linux カーネルとは
Linux カーネルはOSの核となる基本的かつ重要なソフトウェアです。
- アプリケーションとコンピュータのハードウェアを結び付ける仕事
- コンピュータにはHDD, CPU, メモリなどアプリケーションが動作する際に必要になるハードウェア資源が何種類もあるため、それらが一元的に管理されていないと取り合いになってしまうためカーネルが必要
環境
ハンズオンをするための環境はお手軽にサーバを作成し、ターミナルも触れる AWS Cloud9 1 を利用するのがおすすめです。
- AWS Cloud9
- Ubuntu 18.04
カーネルの実体
uname -rで動いているカーネルのバージョンを表示する/bootディレクトリにあるvmlinuz-x.xx.x-xxxx-awsがカーネルの実体
- ファイルサイズが 8.5MB ほどしかないことが分かる
$ uname -r 5.3.0-1033-aws $ ls -lh /boot | grep vml -rw------- 1 root root 7.6M Aug 27 2018 vmlinuz-4.15.0-1021-aws -rw------- 1 root root 8.5M Aug 5 14:10 vmlinuz-5.3.0-1033-aws -rw------- 1 root root 8.5M Sep 5 16:49 vmlinuz-5.3.0-1035-awsLinux カーネルは必要不可欠ではない機能を分離して、別途オブジェクトファイルで管理し必要な時に使えるようにしています。
理由は仮にカーネルに機能を集約した場合、必要と思われる機能を全て最初からコンパイルし静的リンクしておく必要があり、その機能の多くは実際には使用されていないにも関わらずメモリに常駐し、新たな機能が必要になるとカーネル全体の再ビルドと再起動が必須となってしまうためです。
このように、OS動作中のカーネルを拡張するコードを含むオブジェクトファイルをローダブル・カーネル・モジュール(LKM)と呼びます。
ローダブル・カーネル・モジュールは
/lib/modules/カーネルバージョン/kernel/配下に置かれています。$ ls -F /lib/modules/5.3.0-1033-aws/kernel/ arch/ crypto/ drivers/ fs/ lib/ net/ virt/ wireguard/ zfs/カーネルに既にロードされているモジュールは
lsmodコマンドを用いて一覧表示可です$ lsmod Module Size Used by ufs 81920 0 msdos 20480 0 xfs 1273856 0 xt_conntrack 16384 1 xt_MASQUERADE 20480 1 nf_conntrack_netlink 45056 0 nfnetlink 16384 2 nf_conntrack_netlink xfrm_user 36864 1 xfrm_algo 16384 1 xfrm_user <以下略>プロセス管理
実行中のプロセスの表示
実行中のプロセスは
psコマンドで表示します。$ ps aux | head -n 10 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.1 0.7 225392 7804 ? Ss 09:55 0:04 /sbin/init root 2 0.0 0.0 0 0 ? S 09:55 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? I< 09:55 0:00 [rcu_gp] root 4 0.0 0.0 0 0 ? I< 09:55 0:00 [rcu_par_gp] root 6 0.0 0.0 0 0 ? I< 09:55 0:00 [kworker/0:0H-kb] root 9 0.0 0.0 0 0 ? I< 09:55 0:00 [mm_percpu_wq] root 10 0.0 0.0 0 0 ? S 09:55 0:00 [ksoftirqd/0] root 11 0.0 0.0 0 0 ? I 09:55 0:01 [rcu_sched] root 12 0.0 0.0 0 0 ? S 09:55 0:00 [migration/0] <以下略>1レコードが1プロセスにあたり、複数のプロセスが動いていることがわかると思います。
メモリ管理
Linux では各プロセスが使用するメモリ空間を物理アドレスから分離し、プロセス単位の分離を実現すると共に、実質的に使用可能なメモリ量を増大させています。メモリ空間はページ(決まった大きさの単位)に分けられていて、プロセスが仮想メモリ空間を利用するだけ、ページ単位で物理メモリを割り当てています。これを ページング方式 と呼びます。
ページ回収
Linux はプロセスがディスクに対してファイルを読み書きする時に、カーネルがその内容をページキャッシュというメモリ領域に一時的に保存することで同じファイルにアクセスする時にキャッシュ上のファイルを利用できるので処理が高速化します。
ページキャッシュは空きメモリが少なくなると捨てられ、キャッシュを解放して空きメモリにすることをページ回収と呼日ます。ページキャッシュの使用量は
freeコマンドの buff/cached にあたる部分になります。(以下の例だと554MB)$ free -m total used free shared buff/cache available Mem: 978 321 102 2 554 490 Swap: 488 63 425
/proc/sys/vm/drop_cachesに3を書き込むとページキャッシュを開放します。事前にsyncコマンドでディスクにファイルを反映しておくとよいです。$ sync $ sudo sh -c "echo 3 > /proc/sys/vm/drop_caches" $ free -m total used free shared buff/cache available Mem: 978 325 526 2 126 520 Swap: 488 63 425buff/cache の値が減り、free-Mem の値が増加しメモリが解放されていることが分かる。
デバイス管理
各種周辺機器(デバイス)は、プログラムとデータをやり取りするときにデバイスファイルを利用します。Linux では、デバイスは抽象化されてファイルとして扱われます 2。
デバイスファイル一覧は、
/devディレクトリ以下に存在します。$ ls -F /dev autofs log@ port tty13 tty31 tty5 ttyS1 vcsa6 block/ loop-control ppp tty14 tty32 tty50 ttyS2 vcsu btrfs-control loop0 psaux tty15 tty33 tty51 ttyS3 vcsu1 char/ loop1 ptmx tty16 tty34 tty52 ttyprintk vcsu2 console loop2 pts/ tty17 tty35 tty53 udmabuf vcsu3 core@ loop3 random tty18 tty36 tty54 uinput vcsu4 cpu_dma_latency loop4 rfkill tty19 tty37 tty55 urandom vcsu5 cuse loop5 rtc@ tty2 tty38 tty56 vcs vcsu6 disk/ loop6 rtc0 tty20 tty39 tty57 vcs1 vfio/ ecryptfs loop7 shm/ tty21 tty4 tty58 vcs2 vga_arbiter fd@ mapper/ snapshot tty22 tty40 tty59 vcs3 vhost-net full mcelog stderr@ tty23 tty41 tty6 vcs4 vhost-vsock fuse mem stdin@ tty24 tty42 tty60 vcs5 xen/ hpet memory_bandwidth stdout@ tty25 tty43 tty61 vcs6 xvda hugepages/ mqueue/ tty tty26 tty44 tty62 vcsa xvda1 hwrng net/ tty0 tty27 tty45 tty63 vcsa1 zero initctl@ network_latency tty1 tty28 tty46 tty7 vcsa2 zfs input/ network_throughput tty10 tty29 tty47 tty8 vcsa3 kmsg null tty11 tty3 tty48 tty9 vcsa4 lightnvm/ nvram tty12 tty30 tty49 tty50. vcsa5ブロックデバイス
xvdaというデバイスファイルは、bが先頭になっています。これはブロックデバイスを意味し、ブロック形式でデータをやり取りする機器(ハードディスクドライブ/メモリ領域などのアドレス指定可能な機器)になります。$ ls -l /dev/xvda brw-rw---- 1 root disk 202, 0 Sep 22 00:02 /dev/xvda
lsblkコマンドでブロックデバイスを表示することもできます。$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 12.7M 1 loop /snap/amazon-ssm-agent/495 loop1 7:1 0 96.6M 1 loop /snap/core/9804 loop2 7:2 0 28.1M 1 loop /snap/amazon-ssm-agent/2012 loop3 7:3 0 97.1M 1 loop /snap/core/9993 xvda 202:0 0 10G 0 disk └─xvda1 202:1 0 10G 0 part /キャラクタデバイス
一方、
ttyというデバイスファイルは、cが先頭になっています。これはキャラクタデバイスを意味し、システムが1バイトずつデータを転送する機器(キーボードなど)になります。$ ls -l /dev/tty crw-rw-rw- 1 root tty 5, 0 Sep 22 00:02 /dev/ttyudev
Linux ではデバイス管理ツールとして udev を利用しています。udev は Linux上のデーモンとして動作し、新しいデバイスがシステムに接続される、またはデバイスがシステムから接続を解除された場合、カーネルは udevに通知します。udev は通知を受けるとルールに基づいてデバイスファイルを作成します。
udevadm monitorによって udevのイベントを表示します。$ udevadm monitor monitor will print the received events for: UDEV - the event which udev sends out after rule processing KERNEL - the kernel uevent <以下略>ファイルシステム
ファイルシステムとはコンピュータのリソースを操作するための Linuxカーネルの機能です。簡単にいうと
ファイルをとり扱うための枠組みと方法です3。ファイルとは、主に補助記憶装置に格納されたデータを指しますが、デバイスやプロセス、カーネル内の情報といったものもファイルとして提供するファイルシステムもあります。ファイルシステムの種類
- ディスク
- ext4
- ext3
- XFS
- ネットワークファイル共有
- NFS
- SMB/CIFS
- 特殊用途
- procfs, sysfs
- tmpfs
- FUSE
sudo parted -lコマンドで全てのブロックデバイスのパーティション情報を表示します。$ sudo parted -l Model: Xen Virtual Block Device (xvd) Disk /dev/xvda: 10.7GB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 1049kB 10.7GB 10.7GB primary ext4 boot
/proc/filesystemsにカーネルで対応しているファイルシステムの一覧があります。$ cat /proc/filesystems nodev sysfs nodev tmpfs nodev bdev nodev proc nodev cgroup nodev cgroup2 nodev cpuset nodev devtmpfs nodev configfs nodev debugfs nodev tracefs nodev securityfs nodev sockfs nodev bpf nodev pipefs nodev ramfs nodev hugetlbfs nodev devpts ext3 ext2 ext4 squashfs vfat nodev ecryptfs fuseblk nodev fuse nodev fusectl nodev mqueue nodev pstore btrfs nodev autofs nodev overlay nodev aufsVFS
VFS(Virtual File System)とはアプリケーションが様々なファイルシステムに同じ方法でアクセスできるようにするためのカーネルの機能です。VFS があることによって、ローカルな記憶装置にもネットワーク上の記憶装置にも透過的にアクセスできるため違いを意識する必要がなくなります。
VFS が管理する情報の1つに iノードがあります。iノードはファイルとディスクの情報を関連付ける役割を担っています。ディレクトリは、iノード情報を保持することで間接的にファイルを管理しています。
ls -iで左端に表示される数字(280257)が iノード番号にあたります。$ ls -il total 4 280257 -rw-r--r-- 1 ubuntu ubuntu 569 Aug 28 05:46 README.mdiノード情報を詳しく確認するには
statコマンドを利用します。$ stat README.md File: README.md Size: 569 Blocks: 8 IO Block: 4096 regular file Device: ca01h/51713d Inode: 280257 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu) Access: 2020-08-28 06:25:56.732380517 +0000 Modify: 2020-08-28 05:46:13.000000000 +0000 Change: 2020-08-28 06:27:17.072779096 +0000 Birth: -IO
シグナル
カーネルからプログラムに対して、終了や中断、休止などの要求を通知する仕組み。プロセスはシグナルを受け取ると、シグナルの種類ごとに登録してある処理を実行する。
$ cat /proc/interrupts CPU0 0: 43 IO-APIC 2-edge timer 1: 9 xen-pirq 1-ioapic-edge i8042 4: 3576 xen-pirq 4-ioapic-edge ttyS0 8: 2 xen-pirq 8-ioapic-edge rtc0 9: 0 xen-pirq 9-ioapic-level acpi 12: 3 xen-pirq 12-ioapic-edge i8042 14: 0 IO-APIC 14-edge ata_piix 15: 0 IO-APIC 15-edge ata_piix 48: 117991 xen-percpu -virq timer0 49: 0 xen-percpu -ipi resched0 50: 0 xen-percpu -ipi callfunc0 51: 0 xen-percpu -virq debug0 52: 0 xen-percpu -ipi callfuncsingle0 53: 0 xen-percpu -ipi spinlock0 54: 258 xen-dyn -event xenbus 55: 30247 xen-dyn -event blkif 56: 11722 xen-dyn -event eth0 NMI: 0 Non-maskable interrupts LOC: 0 Local timer interrupts SPU: 0 Spurious interrupts PMI: 0 Performance monitoring interrupts IWI: 0 IRQ work interrupts RTR: 0 APIC ICR read retries RES: 0 Rescheduling interrupts CAL: 0 Function call interrupts TLB: 0 TLB shootdowns TRM: 0 Thermal event interrupts THR: 0 Threshold APIC interrupts DFR: 0 Deferred Error APIC interrupts MCE: 0 Machine check exceptions MCP: 13 Machine check polls HYP: 161747 Hypervisor callback interrupts ERR: 0 MIS: 0 PIN: 0 Posted-interrupt notification event NPI: 0 Nested posted-interrupt event
- 投稿日:2020-12-15T17:48:58+09:00
Amazon Linux2 + Freenom + Let's Encrypt で 無料で HTTPS 化する
Amazon Linux2 + Freenom + Let's Encrypt で 無料で HTTPS 化したので、後で同じ作業を行ったときに困らないときようのためにメモ。
基本は Let's Encrypt の作業をメインに書いていく。EC2
- 証明書を発行するための、セキュリティグループ インバウンド 80,443 ポートを開けておく。
Freenom
- ドメイン名を取得済であり、Aレコードを作成済であること。
- www.naata.com IN A IPアドレス
Let’s Encrypt
Let’s Encrypt のCertbot クライアントをインストール
$ sudo amazon-linux-extras install epelcertbot、python-certbot-apache のパッケージをインストール
$ sudo yum install certbot python-certbot-apacheServerNameの編集
httpd.confServerName:www.naata.comcertbotコマンドによるサーバー証明書の取得
$ sudo certbot certonly --webroot -w /var/www/html/ -d www.naata.com$ sudo ls -l /etc/letsencrypt/live/www.naata.com total 4 lrwxrwxrwx 1 root root 56 Sep 25 07:50 cert.pem -> ../../archive/www.naata.com lrwxrwxrwx 1 root root 57 Sep 25 07:50 chain.pem -> ../../archive/www.naata.com lrwxrwxrwx 1 root root 61 Sep 25 07:50 fullchain.pem -> ../../archive/www.naata.com lrwxrwxrwx 1 root root 59 Sep 25 07:50 privkey.pem -> ../../archive/www.naata.com -rw-r--r-- 1 root root 692 Sep 25 07:50 READMEhttpdの再起動
$ sudo systemctl restart httpd.service $ sudo systemctl status httpd.servicessl.confの編集
ssl.confSSLCertificateFile /etc/letsencrypt/live//www.naata.com/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live//www.naata.com/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live//www.naata.com/chain.pem動作確認
$ curl -vv https://www.naata.com
- 投稿日:2020-12-15T17:30:17+09:00
【bash】サーバ作業時のヒューマンエラーを防ぐ
シェルスクリプトをもっと有効活用しよう
「これからどんなプログラミング言語を学ぶべきか?」という命題はいつの時代もみんなの心を悩ませますね。Python は人気急上昇ですし、Java を愛好する人もまだまだ多いです。”いや、C言語はまず押さえておくべきだ” という意見も根強く聞かれます。
みんなそれぞれ、納得できるんですが、最初の言語として僕が初心者の方に敢えて勧めるのはシェル、例えば bash です。awk や sed を使えば、コマンドラインでもそこそこの事ができますし、Linux なら設定スクリプトは bash ですから読めるとかなり役立ちます。ちょっとした事なら、Python を使うよりずっと効率的で分かりやすかったりもします。例えばどんな風に使う?
サーバを運用する上で、コマンドラインで作業をすることが多いです。特に注意が必要なのは、実行中のプロセスを終了する作業です。こういう場合は ps コマンドでプロセスIDを調べて、kill コマンドで終了、ということになるんですが、何度もやってると精神的にきついです。特に夜中、草木も眠る丑三つ時あたりになると頭も心も疲れてきて、つい間違ったプロセスIDを kill してしまう、などということになって、目も当てられない状況に追い込まれてしまうと大変です・・・。
こういう場合、ちょっとしたスクリプトを書いて作業を簡素化しておくと、楽になる上 間違いも無くなって得した気分になれます。コマンドラインから1行でプロセスを終了させる例
スクリプトを書く前に、実行中のプロセスのIDを取得してkillする、という流れをみてみます。
- 実行環境
MacOS 11.0.1
GNU bash, version 3.2.57(1)-release
awk version 20200816ここで、自分で作った "stupid" というプログラムを終了させる場合を考えます。
psコマンドで引数を -ef としてプロセスID を調べ、kill することになります。
まず、ps -efの振る舞いを調べてみます。head で最初の2行を表示してみます。ps -ef | head -n 2 UID PID PPID C STIME TTY TIME CMD 0 1 0 0 7:33PM ?? 0:30.22 /sbin/launchd最初の項目がユーザID、2番目の項目がプロセスID、最後の項目が実行ファイル名だと分かりますね。
運用者のユーザIDで走っている実行ファイルのプロセスIDを指定して kill すれば良いわけです。
# 他のユーザが同名で実行しているプロセスをkillしないよう注意が必要です。例えば、以下のような感じで対象のプロセスIDを調べてみましょう。ちなみに bashの環境変数 $UID に自分のユーザIDが格納されているので、これを利用してみます。
ps -ef | awk '{if ($1 == '${UID}') {print $0} | grep stupid | grep -v grepやってることは、
① ps -ef でプロセス一覧を表示
② awk を使って最初の項目が自分のユーザIDと同じ行を取り出す
# bash の変数と awk内の変数は区別する必要があるため、表記法に注意
参考:shellスクリプト変数をawkに渡す
③ grep で、終了対象の実行ファイルの名前の行を取り出す
③’( grep -v で、③ で一緒に抽出されてしまう自分自身を除外する)これで当該プロセスに関する行を抽出できます。出力結果はこんな感じ。
502 4225 2319 0 12:23PM ttys002 0:00.00 ./stupidここで、2番目の項目がプロセスIDでしたね。この場合は 4225 です。この部分を取り出して kill すれば良いですね。awk で取り出します。
ps -ef | awk '{if ($1 == '${UID}') {print $0} | grep stupid | grep -v grep | awk '{print $2}'この実行結果で表示されるプロセスIDをkillすれば良いわけです。次はここを自動化します。
bash では、(一連の)コマンドをバックスラッシュで囲むと、その結果を返してくれます。よって、プロセスID を間違えず kill するには、以下の通りです。1行でできますね。
kill `ps -ef | awk '{if ($1 == '${UID}') { print $0 }}' | grep $1 | grep -v grep | awk '{print $2}'`指定した名前のプロセスを kill するスクリプト
ただし、都度これを打ち込むのはかえって面倒です。この流れをうまくスクリプトにして、あとは例外処理、エラー処理などを施しておきます。これで後々楽になるしミスも減ります。
ここでは、kill すべきプロセスの名前を引数にとって実行し、以下の流れで処理していきます。実際に kill が発動するのは ⑤ だけで、あとは例外処理です。面倒ですが、一度作っておけば、何度でも使えるので、よしとしてください・・・
① 引数の個数が1つでなければ、使用法を表示し終了。
② 引数で指定した名前のプロセスが2つ以上あればそれを表示して終了
③ 引数で指定した名前のプロセスが存在しなければ、その旨表示して終了
④ 引数で指定した名前のプロセスの概要を表示し、killするか確認
⑤ ’y'キーが押されれば kill を実行
⑥ その他のキーが押されれば、何もせず終了ソースは以下のような感じです。
killprocess.sh#!/bin/bash # 引数の個数が1つでなければ、使用法を表示し終了 if [ "$#" != 1 ];then echo echo "Usage: $0 processname" echo exit 1 fi # ps コマンドで指定の行を取り込み、PSRESULT という変数に格納 PSRESULT=`ps -ef | awk '{if ($1 == '${UID}') { print $0 }}' | grep $1 | grep -v grep |grep -v $0` # 引数で指定した名前のプロセスがいくつあるか数え、PSNUMという変数に格納 PSNUM=`ps -ef | awk '{if ($1 == '${UID}') { print $0 }}' | grep $1 | grep -v grep |grep -v $0|wc -l` # 後々のために、psコマンドのヘッダを PSHEADER という変数に格納 PSHEADER=`ps -ef | head -n 1` # 引数で指定した名前のプロセスが2つ以上あればそれを表示して終了 if [ "$PSNUM" -gt 1 ];then echo echo "More than 2 \"$1\" are running as bellow." echo echo $PSHEADER ps -ef | awk '{if ($1 == '${UID}') { print $0 }}' | grep $1 | grep -v grep |grep -v $0 echo echo "You should select one of them." echo exit 1 fi # 引数で指定した名前のプロセスが存在しなければ、その旨表示して終了 if [ -n "$PSRESULT" ];then PID=`echo $PSRESULT|awk '{print $2}'` else echo echo "No such Process. Cannot kill." echo exit 1 fi # 引数で指定した名前のプロセスの概要を表示し、killするか確認 # 'y'キーが押されればプロセスをkill を実行 # その他のキーが押されれば、何もせず終了 echo echo " Do you want to kill the process bellow?" echo echo $PSHEADER echo $PSRESULT echo read -p "input (y/n):" input if [ "$input" = "y" ];then kill $PID if [ $? == 0 ];then echo echo " \"$1\" is successfully killed" echo exit 0 else echo echo "Failed..." echo exit 1 fi else echo echo "Did nothing." echo exit 1 fiこんな感じでしょうか。
実際に "stupid" というプロセスを kill するには、chmod u+x killprocess.sh ./killprocess.sh stupidなどとすれば良いでしょう。
うまくいけば、こういう感じで "stupid" を kill することができます。Do you want to kill the process bellow? UID PID PPID C STIME TTY TIME CMD 502 5482 2182 0 5:28PM ttys000 0:00.00 stupid input (y/n):y "stupid" is successfully killedセキュリティ上、このスクリプトは作業が済んだらサーバから消しておくことも必要でしょうね。
まとめ
ssh でサーバに乗り込んで作業する際、十分な注意が必要です。たとえ手順書を作っていても、実際の作業時には想定外のインシデントが起きるのは当然と考えておかないといけません。やはり、できるところは事前にスクリプトを作っておいて、作業の効率化、信頼度向上を図ることはなんだか良いんじゃあないかと思います。
- 投稿日:2020-12-15T17:09:26+09:00
Linuxについて①
Linuxはosの一種であり、コンピュータを動かすための基本ソフト
1991年にリーナス・トーバルズが開発▼用途
サーバー(web業界)
組み込み
デスクトップ等々▼特徴
オープンソースである⇨誰でも自由に使える
品質の高いソフトウェアが利用できる▼欠点
日本語対応していない
商用アプリケーションがあまり存在しない(画像、動画、音声が苦手)以上
- 投稿日:2020-12-15T15:21:27+09:00
盛り盛り nc
nc
TCP/UDPの調査とかに使うらしい
何に利用した?
tcpdumpの動作確認
普通の使い方は知らんし想像もできん
何が出来るの?
TCP/UDPのポートを指定して読み書きが出来る
もっと色々出来るが、どうせ忘れるので知らないでおく操作ログ
1. ポートをlisten
$ nc -l 543212. リッスンの確認
$ lsof -i:543213. 接続
$ telnet 127.0.0.1 543214. 接続の確認
$ lsof -i:54321 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 12415 qon 3u IPv4 0x4fcf6657625b83a1 0t0 TCP *:54321 (LISTEN) nc 12415 qon 4u IPv4 0x4fcf665773bce079 0t0 TCP localhost:54321->localhost:50191 (ESTABLISHED) telnet 12420 qon 3u IPv4 0x4fcf6657756dde89 0t0 TCP localhost:50191->localhost:54321 (ESTABLISHED)所感
どのサイトもスイスアーミーナイフに例えているけど、何それ使ったことない
- 投稿日:2020-12-15T10:53:10+09:00
今さらながらのSSH纏め
sshd_config
sshd_config 設定項目 Port SSHで使うポート番号、基本22 Protocol バージョン、今は2系 ListenAddress 接続を受け付けるアドレス HostKey ホスト鍵ファイルのパス syslogFacility ログのファシリティ LogLevel ログのプライオリティ LoginGraceTime ログインを試みることのできる接続時間 PermitRootLogin rootログインの許可/禁止 StrictModes パーミッションを厳密にチェックするかどうか MaxAuthTries 認証を試みることのできる最大回数 PubkeyAuthentication 公開鍵認証を許可するかどうか AuthorizedKeysFile 公開鍵を登録するファイル PasswordAuthentication パスワード認証の有効/無効 PermitEmptyPasswords 空パスワードの有効/無効 UsePAM PAMを使用する X11Forwarding X11フォワーディングの有効/無効 AllowUsers ログインを許可するユーザー DenyUsers ログインを拒否するユーザー AllowGroups ログインを許可するグループ DenyGroups ログインを拒否するグループ Subsystem 外部システムを指定 ホスト認証とユーザー認証
ホスト認証
- 公開鍵暗号方式を用いて、ホストの正当性を確認する。
- 公開鍵暗号方式では、公開鍵と秘密鍵のペアを使って認証を行います。
- OpenSSHをインストールすると、ローカルホスト用の公開鍵と秘密鍵が作成されます。
秘密鍵は外部に漏れないように管理してください。(アクセス権は、所有者であるrootのみ読み書き可能となっています。)
ホストの公開鍵と秘密鍵はユニークなものです。
SSHでの接続ごとに、ホストの公開鍵(ホスト鍵)がクライアントへ送信されます。
クライアントは、所属しているホスト鍵と一致するかどうか確認することで、ホストに正当性を確認でできます。
ホスト鍵は~/.ssh/known_hosts に格納されます。
初回接続時には、~/.ssh/known_hosts にはホスト鍵が登録されていないため、登録するメッセージが表示され、ホスト鍵が登録されます。
あらかじめサーバー管理者より鍵のフィンガープリントを入手しておけば、本物であるかどうか確認できます。
# ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub 256 SHA256:g4M/xzp2OxkFk9Ym9EGhNV+S7x6tTW6aaVg1V7IgF0g no comment (ECDSA)
- 次回以降は、接続先ホストから送られてきたホスト鍵を known_hosts内の鍵と比較し、問題がなければ、ユーザー認証に進みます。
公開鍵認証
- ホスト認証を終えると、次にユーザー認証に進みます。
- ユーザー認証はまず公開鍵認証が試されます。
- 公開鍵認証は、一組の公開鍵と秘密鍵を使います。
- 公開鍵で暗号化したデータは、ペアとなる秘密鍵でのみ復号できます。
- 秘密鍵となる電子署名は、ペアとなる公開鍵で検証できます。
公開鍵と秘密鍵のペアを ssh-keygen で作成します。
# ssh-keygen -t rsa次に、ユーザーの公開鍵ファイルを接続先ホストの ~/.ssh/authorized_keygen に登録します。
鍵ファイルはあらかじめ、scp などで転送しておきます。(ssh-copy-id を使うと、簡単に公開鍵を接続先ホストに登録できます。)$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys $ chmod 600 ~/.ssh/authorized_keysSSHで接続します。
$ ssh testuser@server.naata.comセキュリテイ
パスワード認証の禁止
PasswordAuthentication norootログインの禁止
PermitRootLogin noログインユーザーの制限
※指定しなかったユーザーは全て禁止となります。
AllowUsers testuser設定例
- サーバー server.naata.com(192.168.250.100) user01
- クライアント client.naata.com(192.168.250.200) user02
sshd.configPort 22 ListenAddress 0.0.0.0 HostKey /etc/ssh/ssh_host_key HostKey /etc/ssh/ssh_host_key_rsa_key HostKey /etc/ssh/ssh_host_key_dsa_key SyslogFacility AUTHPRIV LogLevel INFO LoginGraceTime 2m PermitRootLogin no StricModes yes MaxAuthTries 6 #公開鍵認証 PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys #パスワード認証 PasswordAuthentication yes PermitEmptyPasswords no UsePAM yes X11Forwarding yesパスワード認証でログインしてみる。
なお、空パスワードでの認証は no なので、パスワードは必須である。
host名でアクセスを設定する 場合も参照。$ ssh user01@192.168.250.100 もしくは $ ssh user01@server.naata.com公開鍵認証をやってみる。
まず、クライアント側で公開鍵と秘密鍵を作成します。$ ssh-keygen -t rsa公開鍵をサーバー側へコピーする。
$ ssh-copy-id -i .ssh/id_rsa.pub user01@server.naata.com秘密鍵を使って、ログインをしてみる。
$ ssh -i id_rsa nginx-usero1@server.naata.comまた、.ssh/config 使って簡単に接続できるようになるので、↓の記事も参考になります。
~/.ssh/configについて