ホーム » コンピュータ » Linux (ページ 2)

Linux」カテゴリーアーカイブ

サーバ⚙

アーカイブ

カテゴリー

speedtest-cliとrrdtool

インターネットとの通信速度を計測する speedtest-cli で Linux の上で測定できそうなので、毎日測定するようにしてみた。MRTG を単純に使うと5分おきになってしまうので、rrdtool を使って1日1回更新にてデータを生成させる。

#!/usr/bin/perl                                                                                                                             

my $pgname = "speedtest" ;
my $rrdfile = "/var/lib/munin/localdomain/localhost.localdomain-$pgname.rrd" ;
my $graphfile = "/var/cache/munin/www/localdomain/localhost.localdomain/$pgname.png" ;
my $rrdtool = "/usr/bin/rrdtool" ;
my $speedtest = "/usr/local/sbin/speedtest-cli" ;

my $time = time() ;
my $debug = 0 ;

sub fetchvalue {
    my ($upv , $dwv) = @_ ;
    my $upload = 0 , $download = 0 ;
    open( FH , "$speedtest |" ) or die( "Can't open $speedtest." ) ;
    while( my $line =  ) {
        if ( $line =~ /^Upload:\s*([\d\.]+)\s*(M|K|)bit\/s/i ) {
            $upload = $1 ;
            $upload *= 1000000 if ( $2 eq "M" ) ;
            $upload *= 1000 if ( $2 eq "K" || $2 eq "k" ) ;
        }
        if ( $line =~ /^Download:\s*([\d\.]+)\s*(M|K|)bit\/s/i ) {
            $download = $1 ;
            $download *= 1000000 if ( $2 eq "M" ) ;
            $download *= 1000 if ( $2 eq "K" || $2 eq "k" ) ;
        }
    }
    close( FH ) ;
    $$upv = $upload ;
    $$dwv = $download ;
}

sub create {
    my $cmd =
        "$rrdtool create $rrdfile"
        ." --step 86400"
        ." DS:upload:GAUGE:200000:0:U"
        ." DS:download:GAUGE:200000:0:U"
        ." RRA:LAST:0.5:1:7"
        ." RRA:AVERAGE:0.5:3:7"
        ." RRA:MIN:0.5:3:7"
        ." RRA:MAX:0.5:3:7"
        ;
    print $cmd."\n" if ( $debug ) ;
    system( $cmd ) ;
}

sub update {
    # rrdファイルが無ければ作る                                                                                                             
    create()
        unless( -f $rrdfile ) ;
    # 値を取得して更新                                                                                                                      
    my $upv , $dwv ;
    fetchvalue( $upv , $dwv ) ;
    my $cmd =
        "$rrdtool update $rrdfile"
        ." N:$upv:$dwv"
        ;
    print $cmd."\n" if ( $debug ) ;
    system( $cmd ) ;
}

sub graph {
    my $start = $time - 3600*24*200 ;
    my $cmd =
        "$rrdtool graph $graphfile"
        ." --imgformat PNG"
        ." --start $start"
        ." --end $time"
        ." --title \"SpeedTest\""
        ." --height 150"
        ." --font DEFAULT:7:Consolas"
        ." --vertical-label \"bit/sec\""
        ." --color FRAME#f3f3f3"
        ." --color AXIS#F3F3F3"
        ." --color SHADEA#f3f3f3"
        ." --color SHADEB#f3f3f3"
        ." --color ARROW#f3f3f3"
        ." COMMENT:\"               cur       avg         min         max\n\""
        ." DEF:upload=$rrdfile:upload:LAST"
        ." LINE:upload#00FF00:\"Upload  \""
        ." GPRINT:upload:LAST:\"%6.2lf%s /\""
        ." GPRINT:upload:AVERAGE:\"%6.2lf%s /\""
        ." GPRINT:upload:MIN:\"%6.2lf%s /\""
        ." GPRINT:upload:MAX:\"%6.2lf%s \n\""
        ." DEF:download=$rrdfile:download:LAST"
        ." CDEF:download_minus=download,-1,*"
        ." LINE:download_minus#0000FF:\"Download\""
        ." GPRINT:download:LAST:\"%6.2lf%s /\""
        ." GPRINT:download:AVERAGE:\"%6.2lf%s /\""
        ." GPRINT:download:MIN:\"%6.2lf%s /\""
        ." GPRINT:download:MAX:\"%6.2lf%s \n\""
        ." > /dev/null"
        ;
    print $cmd."\n" if ( $debug ) ;
    system( $cmd ) ;
}

if ( @ARGV > 0 && $ARGV[0] eq "config" ) {
    create() ;
} elsif ( @ARGV > 0 && $ARGV[0] eq "update" ) {
    update() ;
} elsif ( @ARGV > 0 && $ARGV[0] eq "graph" ) {
    graph() ;
} else {
    update() ;
    graph() ;
}

HomeKit/homebridgeをラズパイで再開

一時期、google home notifier のインストールで削除した Siri を使うための HomeKit 互換の homebridge を raspberry-pi の上に再インストールを行った。

Google Home Mini を喋らせるためにインストールした google home notifier では、node.js を使うため(あとで問題がないと分かったけど)に、一旦機能を止めていたけど、機能の競合の起こりにくい raspberry-pi に暇つぶしも兼ねて homebridge を入れる。

インストールにあたり、赤外線リモコンの制御の python-broadlink を raspberry-pi にインストールしたので、単独でテレビのON/OFF/ビデオ入力切替の cec もあるから、サーバを活用しなくても済む。

手順は、過去の自分のインストールメモを参考。ちょっと手間取ったけど。

ということで、

  • テレビ,チューナー,PS4のON/OFF
  • 2つの照明のON/OFF
  • 室内/室外の温度計の表示

が、Hey, Siri で可能。

geoipdeny より kr, tw, hk を削除

最近、自宅よりアクセスできないサイトがあるみたい。特に日本のページのはずだけど、WiFi を切って携帯キャリア接続にすると、問題なく見える。あるとすれば、自宅のファイアウォールの問題か。

自宅では、IPアドレスの国ドメイン割り振り情報を元に、特定の国の IP アドレスをフィルタで接続を拒否している。対象国は自宅サーバへのアクセス履歴で私に縁の無い国から選んだ。でも、最近ではネットワーク接続的に近隣の国のサーバを経由している場合もある。そうなってくると、韓国kr、台湾tw、香港hk の制限が問題になっている可能性が高い。

ということで、これらの国を削除してフィルタを作り直し。

MacBookAir(2011年購入)にUbuntu18を入れる

随分前に購入してSSD入れ替えやバッテリー入れ替えをして愛用機ではあったが、最近は全然使っていなかった 2011年購入のMacBookAir だけど、知り合いが Ubuntu 入れてた記事があったので、自分も入れてみた。MacOS だと、1つの Apple のアカウントに紐付けされている PC が多くて、バックアップのメモリが足りないとか警告が来るし。

インストールは、書いてある通りに進めればいいけど、インストールするためのUSBをGPT(GUID Partition Table)でフォーマットするのに一手間。最近の MacOS では、GPT でのフォーマット機能は隠してあるみたい。やむなくコマンドラインにて作業。

$ diskutil eraseDisk FAT32 SECDISK GPT /dev/disk3
  # FAT32形式、ボリュームラベル=SECDISK、GPTでフォーマット

あとは、Etcher とかいう、GPT などにも対応した Image 書き込みソフトで、ブート USB を作って、option キーを押しながら boot させ、EFI のブートメニューから Ubuntu を選ぶ。

日本語のキーボード周りの設定がちょっと面倒だけど、簡単 Linux 環境のできあがり。

WordPress多要素認証をTwo Factorに変更

WordPress は広く普及しているCMSソフトだからこそ、いい加減な設定だと乗っ取り被害も多く、パスワードの管理は極めて重要。

miniOrange

その中で、今までは miniOrange 社の 2段階認証プラグインを使っていた。機能も多く便利だったけど、便利な認証が有償機能になり、一般的な”Google Authenticator”のような有効時間付きPIN番号の認証機能を使っていた。

他にも様々な2段階認証の方法が使えるけど、その認証は有償だし、他の認証プラグインを探す。

Google Authenticator

改めて探すと、Google Authenticator という名前の認証プラグインが見つかった。名前通りの”Google Authenticator”対応。でも個人の作者の作品みたい。

上記の Google Authenticator は、認証が”Google Authenticator”とバックアップコードだけど、バックアップコードはメモしておくのが面倒なんだよな。

Two Factor

ということで、さらに探してみたら”Two Factor”というプラグインがある。

作者も Plugins Contribution という団体?だし、多要素認証もメールへの認証コード送信、認証アプリ、FIDO認証キー、バックアップコードと基本的な機能を網羅している。ということで、これを入れて登録。

ファイル操作・リダイレクト・LOG解析

ファイル操作やリダイレクトといったLinuxでのファイルの基本操作については、講義用資料を参照。 実際の操作演習に使うファイルを、Raspberry-Pi によるサーバに入れてある。そのファイルで腕試しをしてね。

ファイアウォールとiptables

インターネットからの攻撃を防ぐには、ファイアウォールが必要となる。外部からの接続をうけるコンピュータは、ファイアウォールがどう設定されているのか把握することが重要。

ファイアウォールとDMZ

ファイアウォールは、パケットの(送信元IPアドレス,送信元ポート番号)、(宛先IPアドレス,宛先ポート番号)を見て、通信を制限するルータであり、専用のファイアウォールではさらに細かい制限を加えたり、通信履歴を保存することができる。

組織向けの外部公開のWebサーバやメールサーバを持つ組織では、外部からの接続をうける必要があり、脆弱性があればサーバは乗っ取りなどの被害に会いやすい。サーバが被害を受けたらファイアウォール内部のコンピュータに被害が広がる(トロイの木馬)のは危険であることから、(1) DMZ(非武装地帯)内部に外部公開のサーバを置き、(2) 対外FireWallで外部からのパケットはすべてDMZだけに通す。(3) 内部FireWall では、DMZ の特定の受信パケットだけ流す様にする。

DMZ内部のサーバは、外部からの攻撃をうけるため、極めて慎重にセキュリティ対策を行う必要がある。

iptables

Linux で FireWall を構築するときには、iptables を用いる。iptables では、主に以下の3つのルール(チェイン)でパケットを制限できる。

  • コンピュータに入ってくるパケットに対するルール(INPUT チェイン)、
  • コンピュータから出ていくパケットに対するルール(OUTPUTチェイン)、
  • コンピュータで中継するパケットに対するルール(FORWARDチェイン)

iptables の設定を見るには、iptables -L を実行する。

$ sudo iptables -L  # すべてのルールを表示
Chain INPUT (policy DROP)
target     prot opt source           destination         
DROP       all  --  anywhere         anywhere      state INVALID
ACCEPT     all  --  192.168.11.0/24  anywhere            
ACCEPT     tcp  --  anywhere         anywhere      tcp dpt:http
ACCEPT     tcp  --  anywhere         anywhere      tcp dpt:https
:
Chain FORWARD (policy DROP)
target     prot opt source           destination         
DROP       all  --  anywhere         anywhere      state INVALID
ACCEPT     all  --  127.0.0.0/8      anywhere            
ACCEPT     all  --  192.168.11.0/24  anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source           destination         
ACCEPT     all  --  anywhere         anywhere      state RELATED,ESTABLISHED

iptables で制限のための設定を間違えると、通信ができなくなるので、基本的な考え方だけを紹介する。

「条件にマッチしたパケットをどうするのか」というルールを、チェインに並べておき、パケットが届くとチェインの先頭からルールを適用し、ACCEPT/REJECT/DROPなどの対応を決める。

iptables でルールを登録する場合は、一般的に以下の書式で、条件1,条件2… をすべて満たすパケットをどうするのかのラベルを最後に記載する。

$ iptables -A チェイン 条件1 条件2 … -j ラベル

$ iptables -P INPUT DROP            # デフォルトポリシーの設定
  # INPUT のルールにどれもマッチしない場合はDROP(パケット廃棄)
$ iptables -P OUTPUT ACCEPT
  # OUTPUT のどのルールにもマッチしなければACCEPT(受信許可)

$ iptables -A INPUT -s 127.0.0.1 -j ACCEPT
  # INPUT の末尾に、"送信元IPが 127.0.0.1 ならACCEPT" を追加

$ iptables -A INPUT --dport 80 -j ACCEPT
  # INPUT の末尾に、"宛先ポートが 80 ならACCEPT" を追加

$ iptables -A INPUT -s 11.22.33.44 -j DROP
  # INPUT の末尾に、"送信元IPが 11.22.33.44 ならDROP" を追加

iptablesのオプション引数
  -P      デフォルトポリシーの設定
  -A      末尾にルールを追加
  -s      送信元IPアドレスの条件指定
  -d      宛先IPアドレスの条件指定
  --sport 送信元ポート番号の条件指定
  --dport 宛先ポート番号の条件指定
  -j      指定ラベルに移動

INPUT chain
  |
<送信元IPが127.0.0.1なら>----ACCEPT
  |
<宛先ポートが80なら>----------ACCEPT
  |
<送信元IPが11.22.33.44なら>--DROP
  |
  DROP

ユーザとリモート処理

Linux ではユーザを切替えながら処理を実行したり、ネットワークを越えて命令を実行することができる。外部から攻撃を受けてバックドアが仕掛けられていて不正侵入をうけているのか確認する時に、どういったユーザの処理を実行しているのか把握し、リモート接続で処理ができるような状態なのか知ることが重要。

ユーザとユーザの切り替え

ユーザ,グループの管理

unix では、ユーザ情報は /etc/passwd , /etc/group で管理している。passwdファイル先頭の、ユーザ番号 0 は、なんでもできる権限を持つシステム管理者 root となっている。ユーザ番号 1~999 は、システムを動かすための特殊なユーザとなっている。1000以上は、実際のユーザに割り当てることが多い。

((( /etc/passwd )))
root:x:0:0:root:/root:/bin/bash
sshd:x:111:65534::/var/run/sshd:/usr/sbin/nologin
tsaitoh:x:1000:1000:Tohru Saitoh,,,:/home/tsaitoh:/bin/zsh
| tsaitoh = ユーザ名
| x       = 昔はパスワードが書いてあった, *ならアカウントロック
| 1000    = ユーザ番号
| 1000    = グループ番号
| Tohru Saitoh,,, = ユーザの名前など
| /home/tsaitoh   = ホームディレクトリ
| /bin/zsh        = シェル
  
((( /etc/group )))
root:x:0:
ssh:x:112:
home:x:1000:tsaitoh
| home = グループ名
| x    = 昔はパスワードが書いてあった, *ならアカウントロック
| 1000 = グループ番号
| tsaitoh = グループに所属するユーザ名(コンマ区切り)

ただし、/etc/passwd, /etc/group は、全ユーザが読めるファイルで、暗号化されたパスワードを覚えるには不向きなので、/etc/shadow , /etc/gshadow に保存されている。

ユーザの確認

自分の情報を確認するには、whoamiid , finger コマンドを用いる。

$ whoami    # ユーザ名を表示
tsaitoh

$ id        # UIDやGIDなどの情報を表示
uid=1000(tsaitoh) gid=1000(home) ....

$ finger    # ユーザの詳しい情報を表示
Login    Name           Tty      Idle  Login Time   Office          Office Phone
tsaitoh  Tohru Saitoh   pts/0          Feb 17 22:47 (192.168.11.xx) 12-3456

su コマンド

ユーザを切り替えるには、su コマンドを用いる(Set User)。別ユーザで命令を実行することもできる。ただし、その別ユーザのパスワードが必要。

$ su root
Password: ●●●●●●●●
# exit

$ su -c whoami root
Password: ●●●●●●●●
root

システム管理者での作業は、危険な命令も実行できる状態なので、作業ミスを減らすためにプロンプトが、# に切り替わる。

ただし、su コマンドは、切り替えるユーザのパスワードが必要である。システム管理作業を複数人で行う場合、管理者パスワードを複数人に教えることになり、セキュリティ的に危険である。

sudo コマンド

そこで、管理者などに登録した人であれば、自分のパスワードで管理者権限を得ることができる sudo (set user do) コマンドを使うのが一般的である。

$ sudo bash
Password: ●●●●●●●● 自分のパスワード
# exit
$ sudo whoami     # 管理者で whoami を実行
root

$ sudo -u foobar  # ユーザ foobar に変更
$ whoami
foobar
$ exit
$ whoami
tsaitoh

システム管理者になれるユーザの設定は、/etc/sudoers に記載されている。一般的に、sudo グループに所属していれば、管理者になれるように設定されていることが多い。

su id bit / スティッキービット

パスワードを変更するpasswdコマンドでは自分のパスワードを変更でき、/etc/passwd や /etc/shadow が書き換えられる。unixのr,w,xの権限だけの知識だと、通常ユーザ自身がpasswd,shadowファイルを書き換えられるのなら、同じファイルに記録されている他のユーザ情報(特にパスワードを変更できるはずである。であれば、他人のパスワードも変更できてしまうのではないのか? 当然、こんなことはできてはいけない。

実は、一時的に他のユーザ権限を借りて作業をするため(システム管理者の権限を借りて作業するため)に、su id bit (スティッキービット)という属性がある。

$ sudo bash
$ passwd
Password: ●●●●●●●
Re enter Password: ●●●●●●●

$ which passwd
/usr/bin/passwd

ls -al /bin/ls
-rwxr-xr-x 1 root root 138856  8月  7  2019 /bin/ls
$ ls -al /bin/passwd
-rwsr-xr-x 1 root root  63960  2月  7 23:54 /usr/bin/passwd

上記の passwd コマンドでは、ファイル属性が – rws r-x r-x となっている。(通常の ls コマンドでは、– rwx r-x r-x となっている。)

su id bit が ON になっているコマンドは、一時的に そのファイル所有者 (/usr/bin/passwd の所有者は root) の権限を借りて命令を実行できる。

ただし、スティッキービットが ON だと、管理者権限で命令を実行することができるが、そのコマンドに不備(脆弱性)があると、システムを乗っ取るためにクラッカーが悪用する場合がある。

((( suid ビットが ON のファイルを探す )))
$ find /usr/bin -perl /u=s -print
/usr/bin/password

リモート作業

ネットワークを越えて命令を実行するには、telnetrshssh コマンドを使う。telnet や rsh コマンドは、通信内容が暗号化されていないため、パケットキャプチャを使われると、パスワードなどを盗むこともできるため、通常は使ってはならない。

telnet (暗号化なしのリモート接続)

$ telnet remote-host   # remote-host という名前のコンピュータに telnet で接続
login: ユーザ名
password: パスワード
$ exit

ssh (暗号化されたリモート接続)

ssh は、通信内容を暗号化して安全にリモートコンピュータで命令を実行するコマンド。リモートコンピュータへの接続(slogin)、リモートコンピュータで命令の実行(ssh)、リモートコンピュータとのファイル転送(scp) などができる。

$ slogin remote-host   # 別コンピュータにlogin
Password: ●●●●●●●●
$ hostname             # 使っているコンピュータ名を調べるコマンド
remote-host
$ exit

$ slogin foobar@remote-host  # 指定したユーザ名(foobar)で接続
Password: foobarのパスワード
$ whoami
foobar
$ exit

$ ssh remote-host ls   # remote-host 上で ls を実行
Maildir

$ ssh foobar@remote-host whoami
foobar

$ scp test.c remote-host:~
  # ファイル test.c を remote-host のホームディレクトリにコピー(アップロード)

$ scp foobar@remote-host:hoge.txt dest-dir
  # リモートホストの hoge.txt を、dest-dir にコピー(ダウンロード)

ネットワークサービスとポートスキャン

外部からネットワーク接続を受けて、どういった処理を実行するようになっているのかを知るための方法を説明する。

ポート番号

ネットワーク通信では、通信する相手を指定するために IP アドレスが用いられるが、サーバでは、複数のプログラムが動いており、どのプログラムと接続するのかを指定するには、ポート番号を用いる。

IPアドレスを電話番号に例えるならば、ポート番号は内線電話番号に相当する。

特に、サーバではクライアントからの通信を待つために、このサービスならばこのポート番号を使うという標準番号が決まっている

SSH    = 22   # リモート接続(暗号化)
TELNET = 23   # リモート接続
SMTP   = 25   # メール送信
DNS    = 53   # DNSサービス
HTTP   = 80   # Web サーバ
POP    = 109,110 # メール受信
IMAP   = 143  # メール受信
HTTPS  = 443  # Web サービス(暗号化)
SMTPS  = 465  # メール送信(暗号化)
IMAPS  = 993  # メール受信(暗号化)
POPS   = 995  # メール受信(暗号化)

ネットワークサービス

サーバでは、クライアントからの接続の受信を待つために、あらかじめプログラムを起動しておく必要がある。
こういうサーバプログラムは、Linux の世界では デーモン と呼ぶことも多い。

ネットワークサービスを起動する方式には、いくつかの方法がある。

スーパーサーバを使う場合

ネットワーク処理のプログラムは、複雑な処理を行うためそのプログラムを起動しておくと、メモリを大量に使用する。古いコンピュータでは、処理速度の低下となるため、利用頻度の低いサーバは、汎用的なサーバを起動しておき、必要に応じてプログラムを起動する。この方法には、inetd とか xinetd が用いられる。

$ vi /etc/inetd.conf
echo stream tcp nowait tsaitoh コマンド名

上記の例では、echo=7番ポート に tcp で接続すると、ユーザ名 tsaitoh の権限で、コマンド名を実行してくれる。

デーモンを起動しておく場合

Linux では ランレベル という状態が決められている。

  • シングルユーザモード(S) – 管理者が作業中で他のネットワーク接続とかを受け付けない状態
  • システム停止(0) – 他の状態からシステム停止に移るための仮想的なランレベル
  • マルチユーザモード(2) – 複数のユーザの接続ができる状態
  • GUI環境付きのマルチユーザモード(5) – X11ディスプレイマネージャが動く状態
((( /etc/inittab の中に以下の記載がある )))
$ cat /etc/inittab
:
# The default runlevel.
id:2:initdefault:
:

$ runlevel   # 現在のランレベルを確認する方法
N 5

sysv-rc 方式

Linux では、ランレベルを変更する init コマンド(init 0 を実行すると、システムを停止できる)を実行すると、

  • /etc/rc移行元ランレベル.d 配下のKで始まるプログラムをファイル名順に実行する。
  • /etc/rc移行先ランレベル.d 配下のSで始まるプログラムをファイル名順に実行する。
$ ls /etc/rc2.d
K01aprx                         S17sudo
K01onedrive                     S17unattended-upgrades
README                          S17uuidd
S01lvm2-lvmpolld                S18acpid
S01pulseaudio-enable-autospawn  S18amavis
S14nfs-common

$ sudo /etc/init.d/apache2 start   # apache2のサーバ起動
$ sudo /etc/init.d/apache2 stop    # 停止
$ sudo /etc/init.d/apache2 restart # 再起動

systemd 方式

上記の sysv-rc 方式は、プログラムの起動スクリプトが shell で書かれているので、(システムが単純な頃は)メンテナンスが容易だったが、(システムが複雑になると)起動処理に時間がかかるのが問題となった。このため、新しい Linux では、systemd というプログラムでサーバを起動する方式にかわった。

$ ls /etc/systemd
journald.conf  network        pstore.conf    sleep.conf  system.conf     user
logind.conf    networkd.conf  resolved.conf  system      timesyncd.conf  user.conf

$ sudo systemctl list-units        # systemd のユニット一覧

$ sudo systemctl list-sockets      # 使用中のソケット一覧

$ sudo systemctl status apache2    # systemd で起動している特定のサーバの状態確認

$ sudo systemctl start   apache2   # systemd でサーバ起動
$ sudo systemctl stop    apache2   # systemd でサーバ停止
$ sudo systemctl restart apache2   # systemd でサーバ再起動

起動中のプログラムの確認

システムが通常状態で起動しているプログラムを確認するには、ps ax を用いる。

$ ps ax    # a 全プロセス表示 x 端末を持たないプロセスも表示
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     2:57 /sbin/init
      2 ?        S      0:00 [kthreadd]
      :
2229038 ?        S      0:03 /usr/sbin/apache2 -k start
      :

PIDがプロセス番号、STATは、S:処理待ち状態、R:実行状態、TIME欄は、のべ実行時間を表す。

各プロセスの親プロセスと子プロセスの関係が知りたい場合には、pstree コマンドを用いる。

$ pstree
systemd-+-/usr/sbin/amavi---2*[/usr/sbin/amavi]
        |-/usr/sbin/apach---11*[/usr/sbin/apach]
        |-ModemManager---2*[{ModemManager}]
        |-NetworkManager---2*[{NetworkManager}]

ここで、見たことのないプログラムが動いている様なら、システムの進入を受けた可能性を疑わないといけない。

ネットワーク通信で受信待ちのプログラムの確認

Linuxで開いているポートを確認するためには、netstat コマンドを用いる。

$ sudo netstat -ltup4
  # -l Listenポート、-t TCP、-u UDP、-p ポートを開いている、-4 IPv4
稼働中のインターネット接続 (サーバのみ)
Proto 受信-Q 送信-Q 内部アドレス     外部アドレス  状態        PID/Program name    
tcp       0     0 localhost:3551  0.0.0.0:*  LISTEN      841/apcupsd         
tcp       0     0 0.0.0.0:imaps   0.0.0.0:*  LISTEN      418280/dovecot  
:

nmap でポートスキャン

netstat コマンドは、対象コンピュータを使っている時には有効だが、他のコンピュータを調べるには、ポートスキャン専用の nmap を使うのが一般的。
ポートスキャンとは、相手のコンピュータに接続するポート番号を変更しながら、通信可能か調べること。

$ sudo nmap localhost
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-17 14:45 JST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0000090s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 982 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
25/tcp    open  smtp
:

nmap で調べるための様々なオプション

$ sudo nmap -A localhost  # OSなどを調べる

$ sudo nmap -p 1-1023 localhost # 1〜1023 までのポート番号を調べる

$ sudo nmap -sU localhost  # UDPのポートスキャン

$ sudo nmap -O localhost   # OSの検出

攻撃を受けているのであれば、wireshark などのパケットキャプチャを使って、パケットの中身を調べる必要がある。

ネットワーク関連の基本

なぜか家族チームで Micro Hardening のイベントに参加予定なので、ネットワーク関連の基礎の説明を家族向けにまとめる。以下の説明は基本的に、Linux 環境に login してのお話。

ネットワークの確認(ifconfig)

接続しているネットワークの状態を確認するには、ifconfig を使う。(Linuxの場合)
Windows であれば、cmd.exe を起動して、ipconfig を使う。

((( Linux の場合 )))
$ ifconfig -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.11.2  netmask 255.255.255.0  broadcast 192.168.11.255
        :
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        :
$ ifconfig eth0   # 特定のインタフェースだけ確認
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.11.2  netmask 255.255.255.0  broadcast 192.168.11.255
        :
$ ip link    # 新しい Linux 系では、ifconfig が無い場合もある。
             # ip link がその代用

((( Windows の場合 )))
C:> ipconfig /all    # Linux の ifconfig -a と同じ

上記のコンピュータでは、IPアドレス(例:192.168.11.2)とサブネットマスクの値(255.255.255.0)が設定されている。IPアドレス AND サブネットマスクの値はネットワーク番号と呼ばれ、192.168.11.0 が同じであれば、同じサブネット内と判断できる。サブネットマスクは、上位bitの1の数で表現することもあり、192.168.11.2/24 という書き方もある。

こういったIPアドレスは、各コンピュータに対してあらかじめ決めた値を設定しておく方法(静的アドレス)と、IPアドレスを管理しているサーバにアドレスを一時的に貸し出してもらう方法(動的アドレス)があり、後者のアドレスを貸し出すサーバは、DHCPサーバと呼ばれる。(DHCPでは、アドレス貸し出しを頼んできた端末に、IPアドレス,サブネットマスク,ゲートウェイ,DNSサーバを通知してくれる。後述)

周囲のコンピュータの確認(arp/ping)

基本、インターネットでは IP アドレスで通信相手を判断するが、同じサブネット内では、各コンピュータに割り振られているMACアドレスでコンピュータを識別している。

arp

このため、同じサブネット内では、IPアドレスとMACアドレスの対照表が必要となってくる。この対照表の情報を交換するためのプロトコルが ARP であり、この対照表を確認・操作する命令が arp コマンド。

$ arp -an    # -a で全ての一覧を表示、-n でホスト名を調べない
? (192.168.11.24) at <不完全> on eth0
? (192.168.11.13) at 62:84:bd:28:xx:xx [ether] on eth0
? (192.168.11.36) at b8:27:eb:ee:xx:xx [ether] on eth0
:
$ ip neigh   # 新しい Linux 系では arp コマンドがない場合もある。
             # ip neigh が替わりになる。

ただし、コンピュータが「このMACアドレスは私のIPアドレスですよ」とアナウンスした結果を一定時間覚えているだけなので、かならずそのコンピュータが生きているかは別の話。サブネットの中で、偽のARPを流すことで他のコンピュータ宛のパケットを盗むことも可能(ARPスプーフィング)である。このため、セキュリティ対策としてMACアドレスとIPアドレスの対応(arp)を監視も重要となる。

ping

ping は、潜水艦のソナー音をイメージするコマンドで、ICMPプロトコルのパケットを、指定した IP アドレスor ホスト名に送って、返答の有無や応答時間を表示する。ping では通常、相手に連続してパケットを送る。ネットワークが不安定な場合には、パケットが相手に届かない場合もあるので、パケット欠落があると icmp_sec= の番号が不連続になる。

$ ping 192.168.11.2
PING 192.168.11.2 (192.168.11.2) 56(84) bytes of data.
64 bytes from 192.168.11.2: icmp_seq=1 ttl=64 time=0.054 ms
^C
$ ping www.google.com
PING www.google.com (172.217.161.228) 56(84) bytes of data.
64 bytes from kix06s05-in-f4.1e100.net (172.217.161.228): icmp_seq=1 ttl=54 time=5.62 ms
64 bytes from kix06s05-in-f4.1e100.net (172.217.161.228): icmp_seq=2 ttl=54 time=5.89 ms
64 bytes from kix06s05-in-f4.1e100.net (172.217.161.228): icmp_seq=3 ttl=54 time=5.93 ms
^C

ただし ping は、特殊な ICMP パケットを送ることで相手コンピュータを攻撃できた事例もあり、返答を返さないシステムもある。

ブロードキャストパケット(ping -b)

IPアドレスで、サブネットマスクとANDをとったネットワーク番号の残りの部分は、ホスト番号と呼ばれる。(例:192.168.11.2/24 であれば、2 の部分) IPアドレスでホスト番号の全bitが1のアドレス(この場合は、192.168.11.255)は、ブロードキャストアドレスと呼ばれ、同じサブネット内の全部のコンピュータにデータを送るときに使う。

((( pingでブロードキャストする場合は、-b オプションが必要 )))
$ ping -b 192.168.11.255
WARNING: pinging broadcast address
PING 192.168.11.255 (192.168.11.255) 56(84) bytes of data.
64 bytes from 192.168.11.19: icmp_seq=1 ttl=64 time=70.5 ms
64 bytes from 192.168.11.18: icmp_seq=1 ttl=64 time=70.8 ms (DUP!)

ルーティング

インターネットでは、コンピュータに固有のIPアドレスを割り振り、サブネットを越えて通信ができる。(インターネットプロトコルIP)

基本的に、通信相手のIPアドレス AND サブネットマスク で求まるネットワーク番号が異なれば、サブネットが異なるので直接通信ができない。この場合は、ルータにパケットの中継を依頼することになる。ルータはゲートウェイとも呼ばれる。

ルータは、複数のサブネットを中継する装置であり、どのネットワーク番号ならばどのルータに送る(ルーティングと呼ぶ)というテーブルを持っている。一般的に、下流の末端のネットワークでは、どのネットワークならこの装置、それ以外はこの装置に送る…といった一覧表を持っている。(静的ルーティング)

一方、様々な末端からのデータが集まる上流のルータでは、末端ネットワークの構成が変化することも多いので、RIPというプロトコルで、ルータが相互にルーティング情報を交換している。(動的ルーティング)

ルーティングの確認(netstat -r)

ルーティングの情報を調べるには、netstat -r コマンドを用いる。

$ netstat -rn   # -r ルーティング情報 -n ホスト名を調べない
カーネルIP経路テーブル
受信先サイト     ゲートウェイ    ネットマスク      フラグ   MSS Window  irtt インタフェース
0.0.0.0        192.168.11.1  0.0.0.0         UG        0 0          0 eth0
192.168.11.0   0.0.0.0       255.255.255.0   U         0 0          0 eth0

$ ip route      # 新しい Linux 系では、ip route を使う

この例では、192.168.11.0/255.255.255.0 というサブネットでは直接通信ができ(ゲートウェイが0.0.0.0)、それ以外のパケット(受信先サイトが0.0.0.0)は 192.168.11.1 のルータに送ることになっている。(デフォルトゲートウェイ)

ルートの確認 traceroute

どういった経路で相手コンピュータまでデータが届いているのかを確認するには、traceroute コマンドを用いる。

traceroute コマンドは、ルーティングを調べながら、各ルータに ping を送った結果を表示する。

((( Linux の場合 )))
$ traceroute www.fukui-nct.ac.jp
traceroute to www.fukui-nct.ac.jp (104.215.53.205), 30 hops max, 60 byte packets
 1  xxxx.xxxx.xxxx (192.168.xx.1)  0.299 ms  0.251 ms  0.354 ms
 2  yyyy.yyyy.yyyy (192.168.yy.254)  0.790 ms  1.976 ms  1.343 ms
 3  ttn103-198-212-1.ttn.ne.jp (103.198.212.1)  4.304 ms  5.127 ms  4.343 ms
 4  ftth-sw1-po-11.ntwk.ttn.ne.jp (202.127.81.33)  3.742 ms  5.580 ms  4.296 ms
 5  core-sw2-la-2.ntwk.ttn.ne.jp (202.127.81.29)  5.477 ms  4.692 ms  4.655 ms
 6  bbr2-2-4.ntwk.ttn.ne.jp (202.127.81.17)  4.895 ms  2.025 ms  1.904 ms
 7  103.246.232.116 (103.246.232.116)  6.707 ms  5.499 ms  6.583 ms
((( Windows の場合 )))
C:> tracert www.fukui-nct.ac.jp  # Windowsではコマンド名が違うので注意

DNSによる名前解決

ここまでの話の中で、IPアドレスは、192.168.11.123 といった値であったが、極めて覚えにくい。このために、コンピュータそれぞれに名前をつけることができる。これをホスト名という。ホスト名も組織化されていると、組織を区別する名前が必要でドメイン名と呼ぶ。ホスト名とドメイン名の全体を単純にホスト名とかコンピュータ名と呼ぶことも多いが、正式には、FQDN と呼ぶ。

FQDN = www.fukui-nct.ac.jp (コンピュータ名とかドメイン名と呼ぶことも多い)
ホスト名 = www
ドメイン名 = fukui-nct.ac.jp

コンピュータ名とIPアドレスの情報を管理するのが、DNS(Domain Name Service) であり、下流の DNS の情報を調べながら 上流の DNS と組み合わされて管理されている。

nslookup or dig

この DNS に問い合わせを行うのが nslookup コマンドや dig コマンドである。コンピュータ名からIPアドレスを調べるには、一般的には nslookup コマンドを用いる。(正引き)

$ nslookup www.fukui-nct.ac.jp
Server:		192.168.11.xxx
Address:	192.168.11.xxx#53

Non-authoritative answer:
Name:	www.fukui-nct.ac.jp
Address: 104.215.53.205

$ dig www.fukui-nct.ac.jp   # もっと詳しい情報を調べる場合はdigを使う

利用者が多いサービスでは、1台のコンピュータで処理するのは大変なので、負荷分散を行うために、同じサービスを提供するコンピュータを何台も並べ、コンピュータ名を調べる度に、その複数のコンピュータのIPアドレスを返す場合もある。(ラウンドロビンDNS)

逆引き

迷惑メールを大量に送ってくるとか、クラッキングをしてくるようなコンピュータの中には、きちんと管理されていない怪しいネットワーク組織からの接続の場合がある。こういう場合には、IPアドレスに対して名前が割り振られていない場合も多い。また、攻撃の踏み台に使われている場合、どういった組織のコンピュータが悪用されているのか調べる必要がある。こういう場合には、IPアドレスからコンピュータ名を調べることも多い。(逆引き)

$ nslookup 192.156.146.100
100.146.156.192.in-addr.arpa	name = sv1.ip.fukui-nct.ac.jp.

$ dig -x 192.156.146.100      # dig で逆引きするときは、-x オプションが必要

逆引きでホスト名が調べられないとか、逆引きしたホスト名で再びIPアドレスを調べるとホスト名が異なる場合は、IPアドレスとドメイン名の管理が怪しい危険なコンピュータの可能性がある。場合によっては、DNSサーバが汚染されていて、コンピュータ名でアクセスしたら悪意のあるサーバに接続される危険性もある。(DNSポイズニング)

パブリック DNS

末端組織のDNSの場合、IPアドレスは組織内でしか使えないプライベートアドレス(例:10.xx.xx.xx , 192.168.xx.xx)の場合、組織内専用の DNS が動いていることが多い。この場合、組織内の DNS と組織外の DNS では、異なる情報が得られる場合もある。

こういう場合は、DNS に問い合わせをする場合に、外部の DNS を指定する。特に、Google パプリック DNS は、DNSサーバのIPアドレスが 8.8.8.8 という覚えやすい値が使われている。

$ nslookup 192.156.146.100 8.8.8.8
100.146.156.192.in-addr.arpa	name = sv1.ip.fukui-nct.ac.jp.

$ dig @8.8.8.8 192.156.146.100      # dig でDNSサーバを指定するときは、@の後ろで指定

DNS の特殊な情報

DNS には、IPアドレスとホスト名以外にも、様々な情報が登録されている。この情報を調べるには、タイプを指定する。(-query=タイプ のオプションをつける)

$ nslookup -query=a www.google.com 8.8.8.8     # IPv4 アドレスを調べる
Name:	www.google.com
Address: 216.58.199.228

$ nslookup -query=aaaa www.google.com 8.8.8.8  # IPv6アドレスを調べる
Name:	www.google.com
Address: 2404:6800:400a:80c::2004

$ nslookup -query=mx fukui-nct.ac.jp 8.8.8.8   # メールを送るサーバを調べる  
fukui-nct.ac.jp	mail exchanger = 10 ews.ip.fukui-nct.ac.jp.

$ nslookup -query=txt tsaitoh.net 8.8.8.8      # その他のTXT情報を調べる
tsaitoh.net	text = "v=spf1 +ip4:xx.xx.xx.xx..."
  # この例では、メールサーバの検証方法 SPF の情報が見れた。

検索 🔎

  My Google     Yahoo

便利サイト