ApacheでUserdirを使用できるようにする。

http://chibi.name/~ユーザ名/ みたいな、「~ユーザ名」を使用できるようにする設定をUbuntuで行う。
なお、Apacheの基本的な設定は完了していることを前提として設定していく。
もしAapacheの設定がまだな場合は、前回の日記のApacheの設定なんかを参考に。

先ずは以下のモジュールを読み込む。

$ sudo a2enmod userdir

/etc/apache2/mods-enabled/userdir.conf の Directoryタブの中を以下のように変更する。

$ sudo vi /etc/apache2/mods-enabled/userdir.conf
...
<Directory /home/*/public_html>
    # SSI(一部制限)やCGIの使用を許可している
    Options IncludesNoExec ExecCGI FollowSymLinks
    AllowOverride None

    Order allow,deny
    Allow from all
</Directory>

設定を反映させる為にApacheを再起動させる。

$ sudo /etc/init.d/apache2 restart

$HOMEにpublic_html/ を作成し、試しにHTMLファイルをindex.htmlという名前で作成し、ちゃんとページが表示されるか確認してみる。

$ pwd
/home/chibi
$ mkdir public_html

以下のようなURIにアクセスし、きちんとページが表示できるか確認してみる。
http://サーバのIPアドレス/~ユーザ名/

新規ユーザ作成時にそのユーザのホームディレクトリにpublic_htmlを作成したい

/etc/skel 以下にpublic_htmlというディレクトリを作っておけば、新規ユーザ作成時にそのユーザのホームディレクトリ以下にpublic_html/ が作成されるようになる。

$ sudo mkdir /etc/skel/public_html

試しにtestという名前のユーザを作成してみる
$ sudo -i
# adduser test

testユーザの確認が完了し不要になったら後片付けをしておく
# userdel -r test

なお、新規ユーザ作成時に作成したいファイルやディレクトリがある場合は、上記のような要領で、/etc/skel 以下に作成してやればいい。

ユーザディレクトリへのアクセスを制限したい

ユーザディレクトリへのアクセスを制限したい場合は、/etc/apache2/mods-enabled/userdir.conf の設定を以下のように書き換えればOK。以下はLAN内(192.168.1.0/24)からのみのアクセスに制限してある。

$ sudo vi /etc/apache2/mods-enabled/userdir.conf.

    Order allow,deny
    Allow from all
    ↓
    #Order allow,deny
    #Allow from all
    Order deny,allow
    Deny from all
    Allow from 192.168.1
    Allow from 127.0.0.1

上記の編集が完了したらApacheを再起動して設定を反映させてやればOK。

$ sudo /etc/init.d/apache2 restart

Apacheを使ってWebサーバの構築

UbuntuApacheを使用するには、先ず以下のようにしてapache2のパッケージをインストールする。

$ sudo aptitude install apache2

あと、apxs を使用できるようにする為、以下のパッケージもインストールしておく。

$ sudo aptitude install apache2-dev

$ which apxs2
/usr/bin/apxs2

なお、このページで行うApacheの設定の概要は、

  1. 意図しないディレクトリやファイルへのアクセスを禁止する
  2. DocumentRootは/var/www/html
  3. SSIを使用可能にする
  4. Userdirを使用できるようにする
  5. 不要なアクセスについてはログに記録しないようにする
  6. パフォーマンスにちょっとこだわってみる

とりあえずはこんなところで。

Apacheの基本的な設定

/etc/apache2/apache2.conf を以下のように編集する。

$ sudo vi /etc/apache2/apache2.conf

# パフォーマンス重視ならOffのままで
HostnameLookups Off
↓
HostnameLookups On

# 必要以上なマシン情報を出力しない為
ServerTokens Full
↓
ServerTokens Prod

ServerSignature On
↓
ServerSignature Off
 
#LogFormat "%{User-agent}i" agent の下くらいに以下を追記
CustomLog /var/log/apache2/access.log combined

次に、デフォルト状態の /etc/apache2/sites-available/default を見ると非常に長く、/etc/apache2/sites-available/に違うファイルを作った時に共通化できそうな部分もあるので、なるべく defaultファイルは短くするように記述してみる。
そして、もともとdefaultファイルに書いてあったものや追加分は、/etc/apache2/httpd.conf に追記していくことにする。

/etc/apache2/httpd.conf を以下の内容にする。(デフォルトでは空のファイル)
下記の記述は、/etc/apache2/sites-available/default にあった分を追加したり、足りないものを追記したりしている。

$ sudo vi /etc/apache2/httpd.conf

# 下の2つは自分の環境に合わせて編集する
ServerAdmin webmaster@chibi.name
ServerName chibi.name:80

UseCanonicalName Off

# DocumentRootの指定
DocumentRoot "/var/www/html"

# デフォルトのディレクトリへのアクセスの振る舞いを強化する
<Directory />
    Order Allow,Deny  Deny from all
    Options None
    AllowOverride None
</Directory>

# .bakファイルなど意図しないファイルにアクセスさせない
<FilesMatch "(^\.ht|~$|\.bak$|\.BAK$)">
    Order Allow,Deny
    Deny from all
</FilesMatch>

# CVSファイルにアクセスさせない
<DirectoryMatch /CVS/>
    Order Allow,Deny
    Deny from all
</DirectoryMatch>

# 各種マニュアルファイルへのアクセス制御
Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
    Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>
  
# ScriptAlias
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>

# VirtualHostを有効にする際は以下のコメントを外す
#NameVirtualHost *:80

続いて、/etc/apache2/sites-available/default は以下のような内容になる。

$ sudo vi /etc/apache2/sites-available/default

# DirectoryにはDocumentRootを指定してやる
<Directory "/var/www/html">
    # SSI(制限有り)やCGIの使用を許可している
    Options IncludesNoExec ExecCGI FollowSymlinks
    AllowOverride None

    # アクセス制御
    Order allow,deny
    Allow from all
</Directory>

DocumentRootに/var/www/htmlを指定したので、このディレクトリが無い場合は作成しておく。また適切な所有権やパーミッションを設定しておく。

$ sudo mkdir /var/www/html

また、SSIを使用できる設定にしているので、includeモジュールをa2enmodコマンドで読み込んでおく。
SSIを使う必要が無いならこのモジュールは有効にしない。また、defaultファイルに指定したIncludesNoExecなども不要になる。

$ sudo a2enmod include

あとは、色々と微調整を行う。
DirectoryIndexの設定を変更する為、/etc/apache2/mods-enabled/dir.conf を以下のように使用頻度の高い順に変更する。(自分の環境に合わせて)

$ sudo vi /etc/apache2/mods-enabled/dir.conf
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml
↓
DirectoryIndex index.php index.html index.shtml index.cgi

LanguagePriorityの設定を変更する為、/etc/apache2/mods-enabled/negotiation.conf を編集する。優先度順に並んでいるので、jaを一番前に持ってくる。

$ sudo vi /etc/apache2/mods-enabled/negotiation.conf
LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
↓
LanguagePriority ja en ca cs da de el eo es et fr he hr it ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW

Aliasを設定するなら、/etc/apache2/mods-enabled/alias.conf に追記する。

$ sudo vi /etc/apache2/mods-enabled/alias.conf
...
Alias /hoge     "/home/chibi/public_html/hoge"

AddHandlerの設定をする為、/etc/apache2/mods-enabled/mime.conf を編集する。

$ sudo vi /etc/apache2/mods-enabled/mime.conf
...
#AddHandler cgi-script .cgi
↓
AddHandler cgi-script .cgi .pl

server-status/ へのアクセスをLAN内マシンからも許可する。

$ sudo vi /etc/apache2/mods-enabled/status.conf
<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from localhost ip6-localhost
    Allow from 192.168.1.0/24		←追記(自分の環境に合わせて)
</Location>

以上で設定は完了なので、Apacheを再起動して設定を有効にしてやる。これで基本的な設定も完了しているので、試しに/var/www/html 以下にhtmlファイルを作成し、そのファイルにアクセスしてちゃんとページが表示されるかも確認してみる。

$ sudo /etc/init.d/apache2 restart

デフォルトではファイルがあっちゃこっちゃに分割されていて慣れるまでは非常に辛いが、慣れてくると非常に便利になってくる。

※備考

  • DirectoryIndexは、/etc/apache2/mods-enabled/dir.conf
  • LanguagePriorityは、/etc/apache2/mods-enabled/negotiation.conf
  • Aliasは、/etc/apache2/mods-enabled/alias.conf
  • server-statusは、/etc/apache2/mods-enabled/status.conf
  • IndexOptionsは、/etc/apache2/mods-enabled/autoindex.conf
  • Portを変更したい場合は、/etc/apache2/ports.conf。httpd.confのServerNameの部分も忘れずに

長くなってきてしまったので、とりあえず今回はここまででにして、次回以降で最初に記述した設定の概要の続き(4〜)の設定をしていく。

nmapでポートスキャン

Ubuntunmapを使用するには、先ず以下のようにインストールを行う。

$ sudo aptitude install nmap

試しに、LAN内(192.168.1.0/24)にpingスイープを実行してみる。

$ nmap -sP 192.168.1.0/24                                    

Starting Nmap 4.20 ( http://insecure.org ) at 2008-03-06 21:06 JST
Host 192.168.1.1 appears to be up.
Host mikuru (192.168.1.50) appears to be up.
Host haruhi (192.168.1.100) appears to be up.
Host server (192.168.1.120) appears to be up.
Host nagato (192.168.1.150) appears to be up.
Nmap finished: 256 IP addresses (5 hosts up) scanned in 2.255 seconds

この結果では、5ホストが検出された。

次は、server (192.168.1.120)をターゲットにして、このマシンで稼動しているサービスなどを調査してみる。
先ずは、どのポートがオープンしているか調査。ポートはある程度の範囲に絞って調査してみる。

$ sudo nmap -sS 192.168.1.120 -p 21-3306

Starting Nmap 4.20 ( http://insecure.org ) at 2008-03-06 21:12 JST
Interesting ports on server (192.168.1.120):
Not shown: 3276 closed ports
PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
25/tcp   open  smtp
80/tcp   open  http
110/tcp  open  pop3
139/tcp  open  netbios-ssn
143/tcp  open  imap
443/tcp  open  https
445/tcp  open  microsoft-ds
3306/tcp open  mysql
MAC Address: 00:01:80:**:**:** (AOpen)

Nmap finished: 1 IP address (1 host up) scanned in 0.317 seconds

ここでは、21番〜3306番までの範囲で調査。なお、-sS のオプションを付けることによってステルススキャンを実施している。このオプションを付けて実施するにはroot権限が必要となる。

次に、開いていたポートで稼動しているサービスをより詳細に調査してみる。

$ sudo nmap -sS -sV 192.168.1.120 -P0 -p 21,22,80,110,143,3306

Starting Nmap 4.20 ( http://insecure.org ) at 2008-03-06 21:15 JST
Interesting ports on server (192.168.1.120):
PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd or WU-FTPD
22/tcp   open  ssh     OpenSSH 4.3 (protocol 2.0)
80/tcp   open  http    Apache httpd
110/tcp  open  pop3    Dovecot pop3d
143/tcp  open  imap    Dovecot imapd
3306/tcp open  mysql   MySQL (unauthorized)
MAC Address: 00:01:80:**:**:** (AOpen)

Service detection performed. Please report any incorrect results at http://insecure.org/nmap/submit/ .
Nmap finished: 1 IP address (1 host up) scanned in 6.278 seconds

ここでは適当にポートをピックアップして指定し、それらに対して調査を実施している。各サービスでどのようなアプリケーションを使っているかが分かってしまった。
オプション -sV を付けることによって、どのようなサービスが稼動しているかチェックができる。-P0 はホストの発見を省略するオプション。既に192.168.1.120でマシンが稼動していることが分かっているのでこのオプションを付けた。

ヘッダ情報を取得するスクリプト

以下のように、telnet や nc でWebサーバに接続して、HEADメソッドを発行してヘッダ情報を取得できる。

$ telnet chibilog.name 80
Trying 122.21.243.156...
Connected to chibilog.name.
Escape character is '^]'.
HEAD / HTTP/1.0    ←入力

HTTP/1.1 200 OK
Date: Wed, 05 Mar 2008 02:29:39 GMT
Server: Apache
Vary: Accept-Encoding,User-Agent
Connection: close
Content-Type: text/html; charset=EUC-JP

Connection closed by foreign host.

※ chibilog.name は自分で管理しているサイトです。

このヘッダ情報を取得する場面が多いと、意外と面倒臭くなってくるのでスクリプト化する。
以下は、Pythonで上記のようにヘッダ情報を取得するスクリプト

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, urllib2

try:
  host = "http://" + sys.argv[1] + "/"
except IndexError, e:
  print "Error: %s\n" % e
  print "e.g. python " + __file__ + " chibilog.name"
  sys.exit(1)

try:
  fd = urllib2.urlopen(host)
except urllib2.URLError, e:
  print e
  sys.exit(2)

print "\nRequest: %s\n" % fd.geturl()
print "-" * 10 + "Header" + "-" * 10
for key, value in fd.info().items():
  print "%s = %s" % (key, value)

例えば、上記を httpHEAD.py なんて名前で作成した場合は、以下のように引数にホスト名を指定して実行すればOK。

$ python httpHEAD.py chibilog.name

Request: http://chibilog.name/

----------Header----------
transfer-encoding = chunked
vary = Accept-Encoding,User-Agent
server = Apache
connection = close
date = Wed, 05 Mar 2008 02:45:30 GMT
content-type = text/html; charset=EUC-JP

Sambaでファイルサーバの構築

先ずは、以下のようにしてインストールを行う。

$ sudo aptitude install samba

今回、設定する内容としては、

  • LAN内(192.168.1.0/24)からのみアクセス可能
  • 共有用のディレクトリ(/home/data/share)を作成して、Guestアカウントで読み込み・書き込みを可能にする

共有用のディレクトリを作成しておく。

$ sudo mkdir -p /home/data/share
$ sudo chmod -R 777 /home/data
$ sudo chown -R nobody. /home/data

うちの環境だと、/homeをかなり大きく取ってあるので、共有ディレクトリを/home以下に作成したが、ここは自分の環境に合わせて適宜読み替えてしまってください。

続いて、Sambaの設定ファイルを以下のように編集していく。

$ sudo vi /etc/samba/smb.conf
[global]

# Charset
dos charset = CP932		← 追記
unix charset = UTF-8		← 追記
display charset = UTF-8		← 追記
map to guest = Bad User		← 追記


workgroup = MSHOME
↓
workgroup = WORKGROUP


#### Networking ####

hosts allow = 127. 192.168.1.		← 追記


####### Authentication #######

今回は認証などは無しで接続できるようにするので、以下の2つはコメントアウトする
encrypt passwords = true
↓
#encrypt passwords = true

passdb backend = tdbsam
↓
#passdb backend = tdbsam


ファイルの最終行に以下を追加
[share]
comment = Share Directory
path = /home/data/share
public = yes
read only = no
guest ok = yes
guest only = yes

以上の編集が完了したら、Sambaサービスを再起動させる。

$ sudo /etc/init.d/samba restart

以上で設定は完了なので、クライアントマシンから実際に接続してみる。
Windowsからなら「ファイル名を指定して実行」で「\\サーバのIPアドレス」と入力すれば接続ができる。
試しにファイルを書き込みできるか、そのファイルを読み込めるか確認してみる。
また、日本語のファイル名の時に、エクスプローラ上で文字化けしてないことと、実際のシステムに入って、ファイル名が文字化けしてないことを確認する。

サーバ上では以下のコマンドで、現在の接続状況を確認することができる。
以下は、クライアントマシンより、「Astrogation/水樹奈々.mp3」をコピー中の時の様子。

$ smbstatus

Samba version 3.0.26a
PID     Username      Group         Machine                        
-------------------------------------------------------------------

Service      pid     machine       Connected at
-------------------------------------------------------
share        12714   main-pc       Sat Mar  1 02:42:24 2008
IPC$         12714   main-pc       Sat Mar  1 02:48:50 2008

Locked files:
Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time
--------------------------------------------------------------------------------------------------
12714        65534      DENY_WRITE 0x20089     RDONLY     EXCLUSIVE+BATCH  /home/data/share   Astrogation/水樹奈々.mp3   Sat Mar  1 02:48:53 2008
12714        65534      DENY_NONE  0x100001    RDONLY     NONE             /home/data/share   .   Sat Mar  1 02:48:52 2008

ファイルディスクリプタの上限値を増やす

システム全体のファイルディスクリプタの上限値を変更する

ファイルディスクリプタの上限値を増やす設定を、Ubuntuを例として作業を進めていくが、CentOSなどにも適用可能。
とりあえず、現在のファイルディスクリプタの使用状況を確認してみる。

$ cat /proc/sys/fs/file-nr
4256    0       98531

左から、割り当て済みファイルディスクリプタ 、使用中ファイルディスクリプタ 、最大割り当て可能ファイルディスクリプタとなる。
この最大割り当て可能ファイルディスクリプタの値を増やしてみる。/etc/sysctl.conf を開いて、最下行に以下のように追記する。

$ sudo vi /etc/sysctl.conf

# ファイルディスクリプタの上限値
fs.file-max = 794573

ここでは最大割り当て可能値を794573とした。この設定を反映させる為に以下のコマンドを実行する。

$ sudo sysctl -p

再び以下のコマンドでファイルディスクリプタの使用状況を確認してみる。先ほどよりも値が増えていることが確認できる。

$ cat /proc/sys/fs/file-nr
4256    0       794573

各ユーザのファイルディスクリプタの上限値を変更する

現在、chibiユーザでログインしているとして、ファイルディスクリプタの上限値の確認をしてみる。

$ ulimit -n
1024

デフォルトでは1024となっている。この値を増やすには、/etc/security/limits.conf を編集する。
ここでは例として、rootとchibi の値を増やす記述を行う。最終行の「# End of file」の上辺りにでも以下のように追記する。

$ sudo vi /etc/security/limits.conf

# ファイルディスクリプタの softリミット、hardリミット共に 44769 にする
chibi   soft    nofile  44769
chibi   hard    nofile  44769
root    soft    nofile  44769
root    hard    nofile  44769

# End of file

以上の編集が完了したら、再ログインして確認してみる。

$ ulimit -n
44769

Ubuntuでsshdの設定をしてリモートから接続できるようにする

sshdサービスの開始

違うマシンからこのUbuntuマシンに接続して、あれこれできたほうが便利なのでsshdの設定をしておく。
先ずは以下のようにしてインストール。

$ sudo aptitude install ssh

設定ファイルを見ると、rootでのログインが有効になっているのでこれを無効にしておく。

$ sudo vi /etc/ssh/sshd_config

PermitRootLogin no      ← noにしておく

あとは基本的にそのままでOK。PasswordAuthentication については現段階ではとりあえずyesにしておき、あとで一通り公開鍵の登録などが終わったらnoに変更して、パスワードによるログインを無効にしてしまうのがいい。

とりあえず、上記で設定ファイルの変更をしているので、sshdのサービスを再起動しておく。
サービス再起動後は念のため、ちゃんと起動しているか確認してみる。

$ sudo /etc/init.d/ssh restart

$ sudo lsof -nPi:22
COMMAND   PID  USER   FD   TYPE DEVICE SIZE NODE NAME
sshd    10283  root    3u  IPv4  49690       TCP *:22 (LISTEN)
クライアントマシン(Linux)からの接続

続いて、LAN内にもう1台Linuxマシンがあるとして、そのマシンから今回sshdの設定をしたUbuntuマシンに接続したいとする。
ここでは、接続しようとしているマシンをクライアント。
今回sshdの設定をしたUbuntuマシンをサーバ と呼ぶことにする。
また、クライアント、サーバ共にchibiユーザが存在していて、このchibiユーザが操作しているものとする。(ユーザ名は適宜置き換えてください)

クライアントからサーバにsshコマンドを発行すれば、パスワードでのログインは許可しているので、ユーザとパスワードが一致すれば問題無くログインできると思う。なので、次は鍵を利用してのログインをしてみる。
クライアント側(他のLinuxマシン)で以下のコマンドを実行して鍵の生成を行う。

$ ssh-keygen -t rsa

パスフレーズの入力を促される。パスワードだと思って何か文字列を打ち込んでやる。
なお、何も入力せずにEnterを押せば、空のパスフレーズの鍵を生成することができる。
以上で、クライアントの$HOME/.ssh/ 以下に id_rsa, id_rsa.pub が出来上がる。
id_rsa秘密鍵で、id_rsa.pubが公開鍵となる。id_rsa.pubを接続したい先のサーバに登録してやる。
id_rsa秘密鍵なので、このマシンで大切に持っておく。

とりあえず、この公開鍵(id_rsa.pub)をサーバに送ってやる。

$ scp .ssh/id_rsa.pub サーバのIPアドレス:~/

これで、サーバ側の$HOMEにクライアントのid_rsa.pubを転送できたので、以下のように登録してやる。
以下の作業はサーバ側(Ubuntuマシン)での操作となる。

$ mkdir .ssh    ← .ssh/ディレクトリが無かったので作成した
$ cat id_rsa.pub >> .ssh/authorized_keys

以上で完了なので、再びクライアントからサーバへsshコマンドで接続してみる。
今度は鍵方式での認証に変わっている。パスフレーズを空で登録した場合には、パスワードの入力などを一切せずログインすることが可能になる。

あと、普段使用しているマシンがWindowsで、このWindowsマシンから接続したいという場合は、sshクライアントのソフトを使えば可能。
ちなみに僕は、Poderosa というソフトを使用しています。

Windows用のsshクライアントのソフトによって鍵の生成の仕方などは違うので、ここでは省略するが、基本的にはLinuxクライアントマシンでやった作業と変わらず、鍵を生成したら公開鍵をサーバに転送してやり、サーバ側でその公開鍵を登録するという作業になる。
登録する時の注意点としては、$ cat id_rsa.pub >> .ssh/authorized_keys の「>>」の部分。
これを「>」としちゃったりすると、今まで登録した鍵が消えちゃうので注意。