1. phanect

    Fix typo

    phanect
Changes in body
Source | HTML | Preview
@@ -1,467 +1,467 @@
先日「サーバーのセキュリティ設定がなにすればいいかわからない」と相談をうけまして。
自分も初心者の時どこまでやればいいかわからず手当たりしだいにやって沼に入っていたのを思い出しながら自鯖構築したときのメモを元にまとめてみました。
#### 注意
セキュリティ対策は用途や場合などによって違います。
自分で理解したうえで自己責任でおねがいします。
## 対象読者
- Linuxのサーバーを建て慣れていない人
- Linuxはある程度さわれる人(自分でパッケージを入れたり、サービスを止めたりできる)
# ラインナップ
☆は導入の重要度と導入の容易さから個人的偏見からつけた値です。
4つ以上が"最低限やること"だと思ってください。
| sshd |                      |
|:-------|:------------------------------|
|☆☆☆☆☆  |[sshポート変更](#5-ポート変更)|
|☆☆☆☆ |[sshでrootにlogin出来なくする](#4-sshでrootにlogin出来なくする)|
|☆☆☆☆ |[パスワード認証を切る](#4-パスワード認証を切る)|
|☆☆☆ |[ssh可能ユーザーを限定する](#3-ssh可能ユーザーを限定する)|
|☆☆ |[sshdのプロトコルを2に限定する](#2-sshdのプロトコルを2にする)|
|☆☆ |[認証時の時間と試行回数を制限する](#2-認証時の時間や試行回数を制限する)|
|☆ |[sshguard,fail2banを導入する](#1-sshguard-fail2banを導入する)|
|firewall|                      |
|:-------|:------------------------------|
|☆☆☆☆☆  |[使わないポートを閉じる](#5-使わないポートを閉じる)|
|☆☆☆☆ |[ip spoofing対策](#4-ip-spoofing対策) |
|☆☆☆ |[port scan対策](#3-port-scan対策) |
|☆ |[ICMPパケットのfilteringやstealth port scan対策](#1-icmpパケットのfilteringやstealth-port-scan対策) |
|sudo |                      |
|:-------|:------------------------------|
|☆☆☆    |[passpromptを変える](#3-passpromptを変える)|
|☆☆ |[セッションタイムアウトの時間を設定する](#2-セッションタイムアウトを設定する) |
|web(nginx) |                      |
|:-------|:----------------------------------------|
|☆☆☆☆   |[バージョンを見えなくする](#4-バージョンを見えなくする) |
|misc |                      |
|:-------|:--------------------------------|
|☆☆☆☆   |[不要なサービスを止める](#4-不要なサービスを止める)|
|☆☆☆ |[logwatchを入れる](#3-logwatchを入れる) |
|☆☆ |[使わないユーザーをログイン不可にする](#2-使わないユーザーをログイン不可にする)|
|☆ |[umaskを027にする](#1-umaskを027にする) |
# sshd関連
ほとんどのサーバーはsshでアクセスできるようにsshdを常駐させています。
いわば外部からログインする脳関門のようなものなので重要です。
sshdはかなり奥が深いので`man sshd`や`man sshd_config`を読むとたのしめると思います。
## ☆5 ポート変更
sshのポートは標準でTCP 22番ポートですが、一般的すぎるためbotなどから[攻撃がきます](http://d.hatena.ne.jp/horus531/20110119/1295430024)。
そのため、22番以外のポートに変えるのが一般的です。
代替の番号は予約されているポート(`/etc/services`や[wikipedia](http://ja.wikipedia.org/wiki/TCP%E3%82%84UDP%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7%E3%81%AE%E4%B8%80%E8%A6%A7)参照)以外を使うのが理想ですが、SMTPやHTTPなど有名なものに被らなければ(自分や他人が使わなければ)なんでもいいと私は思います。
学校や企業などのネットワークでは上流のfirewallなども考慮にいれて決める必要があります。
```/etc/ssh/sshd_config
Port 1234
```
## ☆4 sshでrootにlogin出来なくする
rootは本丸なので外から直に触れる場所には置かないほうが良いです。
なので、ssh経由でrootにログインできないようにします。
(sudo権限のある一般ユーザーにsshして`sudo su`してrootになることはできます)
rootはどのサーバーにもあるアカウントなので総当り攻撃される危険性があります。
DebianもArchLinuxも**デフォルトがyes**なので自分で設定したほうが安心です。
```text:/etc/ssh/sshd_config
PermitRootLogin no
```
## ☆4 パスワード認証を切る
パスワード認証が有効では辞書攻撃(dictionary attack)される危険があるので、切れるのであれば切ったほうが安全です。
代替の認証は公開鍵方式の認証があります。
公開鍵方式で自分が入れるように公開鍵を`~/.ssh/authorized_keys`に登録した上で切らないと閉めだされてしまいますので注意してください。
(`ssh-keygen`コマンドで秘密鍵を作成し、クライアントの`~/.ssh/config`に登録すると便利です)
(公開鍵登録は`ssh-copy-id`コマンドを使えば便利に登録できます)
```text:/etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
```
何らかの理由でパスワード認証をonにしておく場合は、
空パスワードでのloginを不許可にしておきましょう(たぶんデフォルトはnoですが一応)
```text:/etc/ssh/sshd_config
PermitEmptyPasswords no
```
###### 2014 11/24 22:09追記
`ChallengeResponseAuthentication no`について@mimimizuさんからご指摘をいただきました。ありがとうございます。
## ☆3 ssh可能ユーザーを限定する
sshが可能なユーザーを限定しておくと安心です。AllowUsersはwhiltelist方式ですが、DenyUsersでblacklist方式でもできます。
例えば、Webアプリを`web_app`というユーザーの権限で動かす場合、
直接`web_app`にsshできる必要はないのssh出来ないようにします。
(デプロイを自動化する場合とかは話は別です)
```text:/etc/ssh/sshd_config
AllowUsers hogeuser git
# DenyUsers web_app
```
## ☆2 sshdのプロトコルを2にする
sshdのプロトコル1は脆弱性が[発見されており](http://www.coresecurity.com/content/ssh-protocol-15-session-key-recovery-vulnerability)「もうサポートしないよ」と言われているため、
なにかしらの理由がない限りプロトコル2を使うべきです。
普通はデフォルト値が2のみのはずですが、古いLinuxディストリビューションでは1,2だったりするため、自分で設定したほうが安心です。
```text:/etc/ssh/sshd_config
Protocol 2
```
## ☆2 認証時の時間や試行回数を制限する
コネクションを貼って認証するまでの猶予時間`LoginGraceTime`と、試行回数`MaxAuthTries`を設定しておきます。
```text:/etc/ssh/sshd_config
LoginGraceTime 30
MaxAuthTries 3
```
## ☆1 sshguard, fail2banを導入する
sshguardやfail2banはsshへの総当り攻撃(bruteforce attack)を検知して、
一定時間アクセスを拒否するなどができます。
sshのポート変更をしない場合は導入を検討してください。
☆1の理由は、sshのポート番号を変えポートスキャン対策を行えば、sshのポート番号は攻撃者はわからないため、sshへのbruteforce attackはされにくいであろうという想定のためです。
複数ipからポートスキャンを分散して行えばsshのポートはわかるため絶対にないとは言えないのですが相対的に重要度をさげました。
ここでは紹介にとどめます。
# firewall(iptables)
firewallは許可していないポートやプロトコルでのアクセスを拒否したりログをとったりできます。
(余談ですがアドレスの書き換え(NAT)も出来ます。)
firewallもなかなかに奥が深いのです。
firewallの一つであるiptablesに関しては`man iptables`や`man iptables-extensitons`を参照してください。
設定にはネットワークの知識が必須なので、書籍の`マスタリングTCP/IP`を読んだり自分でネットワークを構築したり業務用ルーターで遊んだりして勉強するのが良いと思います。
systemdでサービスを管理しているときは`systemctl start iptables`するだけでなく、次回の起動時のために`systemctl enable iptables`をするなどを忘れないでください。
## ☆5 使わないポートを閉じる
iptablesを使うのであれば、`/etc/iptables/iptables.rules`(ipv4)と`/etc/iptables/ip6tables.rules`(ipv6)に設定ファイルがあります。
(ディストリビューションによっては`/etc/iptables/rules.v4`(Debian)とかだったりするかもしれません。)
ipv6に関してはここでは触れません。
何も考えなければ下みたいな感じでいいと思います。(archlinuxのsimple_firewall.rulesの改変)
`Allow HTTP connection`で80番ポートを開けています。
sshできるようにsshのポートも開けておいてください。
```text:/etc/iptables/iptables.rules
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p icmp -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# Allow HTTP connection(port:80)
-A INPUT -p tcp --dport 80 -j ACCEPT
# Allow SSH connection(port:1234)
-A INPUT -p tcp --dport 1234 -j ACCEPT
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
COMMIT
```
## ☆4 ip spoofing対策
WANに直接つないでいる場合は、プライベートアドレスやブロードキャストアドレスは偽装されていると思われるのでDROPする処理を入れます。
```text:/etc/iptables/iptables.rules
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p icmp -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# ip spoofing
-A INPUT -s 10.0.0.0/8 -j DROP
-A INPUT -s 172.16.0.0/12 -j DROP
-A INPUT -s 192.168.0.0/16 -j DROP
-A INPUT -d 0.0.0.0/8 -j DROP
-A INPUT -s 127.0.0.0/8 -j DROP
-A INPUT -s 169.254.0.0/16 -j DROP
-A INPUT -s 192.0.2.0/24 -j DROP
# multicast address
-A INPUT -s 224.0.0.0/4 -j DROP
# broadcast address
-A INPUT -d 255.255.255.255 -j DROP
# Allow HTTP connection(port:80)
-A INPUT -p tcp --dport 80 -j ACCEPT
# Allow SSH connection(port:1234)
-A INPUT -p tcp --dport 1234 -j ACCEPT
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
COMMIT
```
##### 参考
- http://www.wdic.org/w/WDIC/IPv4%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9#xE7x89xB9xE6xAEx8AxE3x81xAAxE7x94xA8xE9x80x94
- https://tools.ietf.org/html/rfc6890
#### 別の書き方として(iptables match)
iptablesの機能の一つにmatchという機能があり、アドレスタイプを指定して処理をすることが出来ます。ちょっと実験的ですが。
いろんな方々のiptablesをみてもなぜか直でずらずら書いてあるので、なにか理由があって使っていないのか知らないだけなのかわからないため、先の例では書きませんでした。知ってる方がいらしたら教えてください。
```text:/etc/iptables/iptables.rules
-A INPUT -m pkttype --pkt-type broadcast -j DROP
-A INPUT -m pkttype --pkt-type multicast -j DROP
```
##### 参考
- http://ipset.netfilter.org/iptables-extensions.man.html
- https://wiki.archlinux.org/index.php/iptables
- http://www.netfilter.org/documentation/HOWTO/netfilter-extensions-HOWTO-3.html
- http://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html#ADDRTYPEMATCH
## ☆3 port scan対策
昔はportsentryを使ったりしていましたが、最近はiptablesでするのがモダン(?)なようです。
port一覧はportsentryを参考にしました。
http://wiki.netbsd.org/nsps/portsentry.conf
```text:/etc/iptables/iptables.rules
# locked for 1day (60*60*24 = 86400 sec)
-A INPUT -m recent --name portscan --rcheck --seconds 86400
-A INPUT -m recent --name portscan --remove
# 以下のポートにアクセスしてきたらportscanとみなす
-A INPUT -p tcp -m multiport --dports 1,7,9,11,15,23,70,79,109,110,111,119,138,138,512,513,514,515,540,635 -m recent --name portscan --set -j DROP
-A INPUT -p udp -m multiport --dports 1,7,9,23,66,67,68,69,111,137,138,161,162,474,513,517,518,635,640,641,666,700 -m recent --name portscan --set -j DROP
```
### 別の書き方として(2014/11/27 18:40 追記)
先ほどのやり方だと使わないポートをたくさん書かないといけなかったり、1秒にnパケットきたらのような処理ができないです。
ちょっと考えてみたらもう少し綺麗に書けそうだったので書いてみました。
hashlimitを使ってみました。
```text:/etc/iptables/iptables.v4
# block portscanner(1 day)
-A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
-A INPUT -m recent --name portscan --remove
# ポート開く処理をここに
# portscanner chain
-N portscanner
# register portscanner and log
-A portscanner -m recent --name portscan --set -j LOG --log-prefix "portscan:"
-A portscanner -j DROP
# 10パケット/秒を超えるアクセスがきたらportscan chainに流す(調節すること)
-A INPUT -m hashlimit --hashlimit-name portscan --hashlimit-mode srcip --hashlimit-upto 10/second --hashlimit-burst 10 -j portscanner
```
できればなにも考えずに[psd macher](http://www.netfilter.org/documentation/HOWTO/netfilter-extensions-HOWTO-3.html#ss3.12)を使いたいのですがパッチを当てないといけないようなのでこうしました。
##### 参考
- http://sharadchhetri.com/2013/06/15/how-to-protect-from-port-scanning-and-smurf-attack-in-linux-server-by-iptables/
## ☆1 ICMPパケットのfilteringやstealth port scan対策
ICMPパケットをやステルスポートスキャンもiptablesでフィルタできますが、ネットワークの知識が必要でめんどくさいですし長くなるのでここでは書きません。
しなくても標的にされたりなどしない限りは大丈夫なはずです。
ネットワーク関連の攻撃に興味ある方は以下のリンクを読むと楽しいと思います。
- https://www.npa.go.jp/cyberpolice/server/rd_env/pdf/DDoS_Inspection.pdf
- http://phantom37383.blog.fc2.com/blog-entry-553.html
#### 更に深いiptablesの設定をしたい方へ
読んでいて参考になったサイトなどです。
- `man iptables`と`man iptables-extensions`
- http://qiita.com/suin/items/5c4e21fa284497782f71
- https://www.oregontechsupport.com/articles/icmp.txt
# sudo
## ☆3 passpromptを変える
管理者は`[sudo] password for user:`と表示されるとパスワードを入力したくなる節があるので、ダミーなプロンプトを表示させてパスワードを盗んだりがんばればできます(そんな事態が発生する時点でやばいですが)。
なので私はオリジナルな`passprompt`にしています。
複数サーバーを管理している人がサーバーを間違えていても気づく可能性を増やせる利点もあります。
```text:visudo
Defaults passprompt = "%u@%h -> Password!!! -> "
```
## ☆2 セッションタイムアウトを設定する
デフォルト値ですがArchLinuxでは5分、Debianでは15分のようで意外と長いです。
気になる方はもっと短めにして良いと思います。
意識的に`sudo`を使った後に`sudo -k`することでセッションが切れるのでそれで代替することもできます。
持ち歩きしているArch端末は0.1(6秒)にしています。
(短めにするとメンテ時に結構めんどくさくなります)
```text:visudo
Defaults timestamp_timeout = 3
```
最近こわいと思っていることは、sudoしてセッションが有効な状態でsudoが含まれているシェルスクリプトなどを実行するとセッションが有効なままになってシェルスクリプト内のsudoが有効になることになんどか遭遇しました。
トロイの木馬的にblogなどに、`sudo`させた後にsudoの入ったシェルスクリプトを一般ユーザー権限で実行したようにみせかけて後ろではやばい何かしているとかできそうなので気をつけたいところです。
# webサーバー(nginx)
webサーバーはapacheとnginxの2勢力がありますが、私はいつもnginxを使ってます。
apacheに関してはあまり詳しくないのでほとんど書けません。
参考になるものは、他の方がまとめたものでもよいのですが、やっぱり公式ドキュメントが面白いです。
(読むのはかなり大変ですが)
- nginx: http://wiki.nginx.org/Configuration
- apache: http://httpd.apache.org/docs/2.4/
## ☆4 バージョンを見えなくする
HTTPのレスポンスのServerヘッダにwebサーバーがなにであるかが書いてあります。
標準ではバージョンまで書いてあるのでどの脆弱性をつけばいいかの参考になってしまいます。
(`apache 2.2.25 vulnerability`などでggるとこわいです)
ディストリビューションによってはpathが違うので注意してください。
```text:/etc/nginx/nginx.conf
http {
...
server_tokens off;
...
}
```
apacheでは
```text:/etc/apache/httpd.conf
ServerTokens Prod;
```
#### (apacheに関して)
個人的にapacheを運用するときに注意している点は以下あたりです。
他にありましたらコメントにおねがいします。
- AllowOverride None;
- Options -Indexes -FollowSymLinks;
- Optionsに予期しないものが含まれていないか
- - ServerSigunature off;
+ - ServerSignature off;
# misc
## ☆4 不要なサービスを止める
動かさなくても良いサービスや想定していないサービスが動いていると、
管理者の管理するべきものが増えたり予期しないことが起きたりします。
ArchLinuxやCentOS7などでは`systemctl`コマンドで現在動いているサービスを確認することが出来ます。
最初はなにが必要なサービスかわからないと思いますが、サービス名で調べながらなにが必要かを考えるとスキルアップにつながります。
## ☆3 logwatchを入れる
大量のログの要約を出力するソフトウェアです。ログを纏めてくれるので不正アクセスや不具合発見などがしやすくなります。
メール転送エージェント(MTA)であるpostfixなどを導入すると、毎日メールを送信してくれます。私はこのメールが欲しいのでpostfixと一緒にlogwatchを入れます。
注意としては異常発生時のアラートではなく、ある時刻にスケジュールされた処理なので即時対応はできません。
☆3の理由は、一緒に入れたいpostfixの導入コストが高い(OP25Bなど)という理由とlogwatchが主流になりつつあるsystemdのjournalに未対応という理由で、"そこそこセキュア"であればなくてもいいかなという個人的評価からきてます。
どのような攻撃が来ているかという勉強する上では毎日読むと楽しいと思います。
## ☆2 使わないユーザーをログイン不可にする
`chsh -s`で`/bin/false`か`/sbin/nologin`に設定するとログインできなくなります。
ユーザー一覧は`/etc/passwd`内に書いてあります。
```console
# chsh -s /bin/false nologinuser
# chsh -s /sbin/nologin nologinuser
```
`/sbin/nologin`は、ログインに失敗した趣旨もしくは`/etc/nologin`の内容を表示した後に終了しますが。`/bin/false`は何も表示せずに終了します。
(ディストリビューションによってpathが違うかもしれないので`where nologin`や`man nologin`を参照してください。)
###### 2014/11/26 19:20追記
指摘してもらいまして、一応知識として知っておいたほうがいいと思ったので紹介しました。
## ☆1 umaskを027にする
`umask`は新規生成したファイルパーミッションを司ります。
ディレクトリは`777`ファイルは`666`でデフォルトのumaskは`022`なので、
作成されるパーミッションはディレクトリであれば777-022=`755`ファイルであれば666-022=`644`となります。
umaskを`027`にするとothersのreadとexecができなくなるため、
他のユーザーが新規作成したディレクトリにcdしたりファイルをreadできなくなります。
(最小権限の原則など)
すべてのユーザーに対して適応する場合は`/etc/profile`を変更します。
特定ユーザーであれば`~theuser/.profile`を変更します。
私は`/etc/profile`では027にして必要なユーザーに対しては022にしています。
```text:/etc/profile
umask 027
```
注意点としてはsudoで作成した設定ファイルなどを見るためには、sudoする必要あります。
設定ファイルなどのグループを管理者グループ(wheel)などにすれば、グループに入っている人からはreadはできるようになります。
#### setgidに関して
setuid, setgid, stickyビットという特殊なビットもあります。(setuidも面白いですが紹介にとどめます)
http://ja.wikipedia.org/wiki/Setuid
私は`umask 027`と組み合わせてsetgidをよく使います。
あるディレクトリのsetgidビットを立てると、そのディレクトリ内で作成したファイルやディレクトリのgroupが継承されます。
通常は新規作成した所有権は`theuser:theuser`となりグループ間で共有したいファイルを毎回`chown`する必要がでてしまいますが、
setgidを立てたディレクトリではその必要がなくなります。
umaskやsetgidの知名度が意外と低いので紹介しました。
# おわりに
自宅サーバー(ArchLinux)を作りながら書いたメモを主軸にまとめたため、サーバーの構築が主軸でサーバーの保守というベクトルが弱くなっています。
サーバーの保守で必要なことを個人的に上げてみると、
- サーバーを常に最新にする
- 常に情報収集をする
- 新しい脆弱性
- 新しい・ホットなソフトウェア
の2つだとおもいます。
また、Linuxサーバーのセキュリティに関しては`Linuxサーバーセキュリティ徹底入門`(ISBN: 978-4798132389)が非常によくまとまっています。
最後に一部熟考調べ不足などがあると思いますが、その際はコメントにてご指摘お願いします。