FTPサーバ(vsftpd)の構築(RedHat系編)


おやじは、現在 SuSE で FTP サーバとして ProFTPD を使用していますが、いざというときのために vsftpd についても動作確認しています。その vsftpd も バージョン2.0.1 から SSL/TLS 対応になったので、ProFTPD と同様に SSL/TLS 化してみたところ問題なく動作したので、RedHat でも動かしてみました。サポートしているのは ProFTPD 同様に Explisitモードで、クライアントとしてはこちらで紹介している、「GetIt FTP」や「SmartFTP」や「Filezilla」が使用できます。
なお、本稿では基本的な FTP サーバとしての設定のみ示しますので、SSL 化についてはこちらを参照ください。
また、デーモンの起動方法は standalone と inet モードがあり、RedHat 系のデフォルトは standalone モードですが、ここでは PASV 対応やバーチャルホスト運用には都合が良い inetモード(xinetd) で動作させることを前提に設定していきます。
バージョン2.0.4から、ProFTPDと同様にPASVモードでクライアントに通知するサーバのアドレスとして、pasv_addressでホスト名を指定しておくとデーモン起動時にそのホスト名からIPアドレスに変換したアドレスを通知できるようになりました。従って、inetモード(xinetd)で動作させれば、おやじが考えたような変な対策をしなくてもPASV未対応のルータを使用して動的IP環境下でPASV運用が可能になります。

■vsftpd のインストール

今回は、FedoraCore の spec ファイルを参考にして、管理を簡単にするためrpmを作ってからインストールすることにしました。rpmの作成方法を記述するのは大変なので、これに関してはダウンロードにrpmの他にsrpmを置いておきますので、興味のある方はそちらを見てください。
なお、このrpmはSSL対応になっていますが、設定しなければ通常のFTPサーバとして使用できます。
おやじの所から rpm をダウンロードして、インストールしてください。インストールは、任意の場所(ここでは、/usr/local/src)にRPMを置いて、インストールします。

# cd /usr/local/src
# rpm -Uvh vsftpd-2.0.2-1.i386.rpm


■vsftpd の設定

vsftpd の設定は、/etc/vsftpd/vsftpd.conf で行います。 ここでのFTPの用途は、WWW サーバへのユーザ毎のコンテンツのアップロード(パーミッションの設定が楽)と anonymousFTP でのソフト公開を行うというポリシーで設定してあります。なお、バーチャルホストについては、ProFTPD と同様の方法(xinetd起動として、バーチャルホスト毎にIPアドレスとconfファイルとxinetd用起動ファイルを用意)が採れますので、こちらを参考にしてください。デフォルト設定は anonymous 専用になっており、vsftpd.conf にはほとんど設定が入っていませんので、man を参考におやじなりに設定したものを以下にあげて置きます。 
vsftpd の設定は、大きく以下の3つの設定オプションのカテゴリがありますので、目的に応じて設定する必要があります。
  1. ブール・オプション

    機能に対して YES/NO でその機能をどう扱うかを設定するもので、機能毎にデフォルト値が決まっており、変更する場合のみ記述すればよい。慣れないだけかもしれないが、いろいろなことを考えて設定しようとすると、ProFTPD のほうが設定しやすく感じるのはおやじだけでしょうか?

  2. 数値・オプション

    タイマ等の数値で設定するオプションであり、これもデフォルト値が決まっている。

  3. ストリング・オプション

    ファイルのパス等、ストリング形式で設定するオプションであり、これもデフォルト値があるものとないものがあるので、適宜設定する。

注:いずれの場合も オプション=設定値 の形態をとるが、 「=」を挟んでどちら側にも絶対にスペースを入れないこと。

◆基本的な設定

ここでは、ローカルユーザが FTP で WWW サーバへのユーザ毎のコンテンツのアップロードするという使い方を中心にした設定方法を示します。

  1. ローカルユーザの利用設定

    local_enable=YES (デフォルト:NO)

    vsftpd はデフォルトで anonymous しかサポートしておらず、ローカルユーザはログインできない。本設定を YES とすることで、ローカルユーザ(例えば、oyaji)のログインが可能となる。

  2. ローカルユーザのumask設定

    local_umask=022 (デフォルト:077)

    デフォルトは077であり、このままだとフォルダ作成時のパーミションが700となり、apacheユーザがコンテンツの読みだしができなくなる。従って、FTP では一般的な022とし、パーミションが755となるよう変更する。

  3. 書き込み系コマンドの使用可否

    write_enable=YES (デフォルト:NO)

    デフォルトでは、書き込み系のコマンド(STOR, DLE, RNFR, RNTO, MKD, APPE, SITE)が使用できず、ホームページのデータのアップさえできないが、本設定を YES とすることで書き込みが可能となる。 anonymous で upload を許可する場合にも本設定は YES にしなければならないが、更に anonymous 用の別のオプションが必要である。

  4. ディレクトリメッセージの設定

    dirmessage_enable=YES (デフォルト:NO)

    このオプションのデフォルトはNOであるが、 conf ファイル上は YES になっている。YES の場合、ディレクトリ毎にメッセージファイル(デフォルトのファイル名: .message) を置いておくと、そのディレクトリ一覧を表示するときに当該メッセージをコマンドのレスポンスとして表示できる。メッセージファイル名は、message_file=xxxxx (デフォルト: .message ) オプションで変更できる。

  5. バナーメッセージの設定

    ftpd_banner="任意のメッセージ" (デフォルト: vsftpdのバージョン)

    ログイン時にサーバ名などを表示する時、このオプションで "  " でくくって適当なバナーメッセージを指定する。特に指定していなければ、vsftpd のバージョンが表示される。

  6. データ転送モードの設定

    ascii_download_enable=YES (デフォルト:NO)
    ascii_upload_enable=YES (デフォルト:NO)

    ASCUモードでのダウンロード・アップロードが何故かデフォルトで不可になっている。 YES にしないと、CGI が動かないという痛い目にあう。

  7. Activeモード時のデータコネクションポートの設定

    connect_from_port_20=YES (デフォルト:NO)

    Activeモード時のデータコネクションポートを20番に固定するかどうかの設定で、デフォルトのNOでは任意のポートが使用される。おやじのポリシーは20番に固定なので、ここは YES に設定。20番にしないと、クライアント側環境によってはデータ転送ができない可能性がある。

  8. NATルータ越えでPASVモードでインターネット公開する場合の設定

     最近は、いくつかのメーカや機種で本設定を行わなくてもルータで同等の対応を行うものが増えてきているので、まずは、本設定を行わずにPASVを動かしてみるとよい。対応済みルータで本設定を行うと逆にLISTで止まるようになるので注意が必要。

    pasv_enable=YES (デフォルト:YES)
    pasv_address=ルータのWAN側のIPアドレス (デフォルト:なし サーバのNICアドレス)
    pasv_addr_resolve=YES (デフォルト:NO)
    pasv_min_port=最小ポート番号 (デフォルト:0 任意のポートを使用)
    pasv_max_port=最大ポート番号 (デフォルト:0 任意のポートを使用)

    ・pasv_enable
     デフォルトで PASV モードが有効になっているので、敢えて設定は不要だが PASV は使用したくないなら、NO に設定。

    ・pasv_address / pasv_addr_resolve(pasv_addr_resolveは2.0.4以降)
     固定IPの場合はルータの WAN 側アドレスを書けば良いが、動的IPの場合は変化してしまうので IP アドレスを書くだけでは済まない。 ProFTPd の場合はここにドメイン名を書くことができるので、ルータのWAN側アドレスが牽けるDDNSのドメイン名を書くだけでよかったが、vsftpd では残念ながらそれができない。そこで、考えられるのが WarFtpdで行ったのと同様に スクリプトでアドレス変化を検出し、vsftpd.conf ファイルの本パラメータを強制的に書き換えてしまう方法である。vsftpdの起動を xinetd 経由で行えば、vsftpd.conf のパラメータさえ書き換えてあげれば、起動されるたびに vsftpd.conf を読み込むので変化に追従できることになる。standaloneでは容易ではない。
     この対処方法については、こちらを参考にしてください。

     バージョン2.0.4以降なら、追加されたpasv_addr_resolveオプションをYES とし、ここにルータのWAN側アドレスが牽けるDDNSのホスト名を記述すれば、デーモン起動時に名前解決して得たIPアドレスをクライアントに通知できるようになった。従って、本設定を行いinetモードで起動すれば、動的IPアドレスでも問題なくPASVが使用できるようになる。

    ・pasv_min_port/pasv_max_port
     PASVモードで使用するポート番号(1024以上)の最小と最大で範囲指定する。おやじは、家庭用なのでそれほど多くは必要ないのと使いまわしされるので、とりあえず30ポートとし、他のデーモンで使ってない4000-4029を使用することとし、
     pasv_min_port=4000
      pasv_max_port=4029
    とした。それぞれ、別行で書かないとうまくいかないので要注意。(過去1行で書いて動作しない方がいた。)
     なお、このポートはインターネット側から接続が開始されるので、ルータのスタティックNATでサーバにNATすると同時に、フルタリングも開ける必要がある。

  9. PAM認証の設定

    pam_service_name=vsftpd (デフォルト:ftp)

     PAMサービスで使用するサービスの名前を指定する。 RPM から入れたなら vsftpd になっており、/etc/pam.d 配下に vsftpd ファイルがインストールされているはずなので、特に変更は不要である。

  10. ユーザ制限の設定

    userlist_enable=NO (デフォルト:NO)
    userlist_deny=NO (デフォルト:YES)
    userlist_file=/etc/vsftpd/user_list (デフォルト)

    上記の上2つのパラメータで、ローカルユーザの制限を行う。 なお、/etc/ftpusers で指定されているシステムユーザは本設定とは無関係にログインできない。

    userlist_enable userlist_deny 動 作 概 要
    NO - userlist_file を使用した制御は行われず、ローカルユーザはログイン可能。
    YES NO userlist_file を使用した制御が有効になり、userlist_file ファイル(ユーザを1行づつ記述したリスト)に登録されたユーザのみログインできる。
    YES userlist_file を使用した制御が有効になり、userlist_file ファイル(ユーザを1行づつ記述したリスト)に登録されたユーザはログインできず規制される。

  11. アクセスディレクトリの制限 ( chroot )

    chroot_local_user=YES (デフォルト:NO)
    chroot_list_enable=YES (デフォルト:NO)
    chroot_list_file=/etc/vsftpd/chroot_list (デフォルト)

    ローカルユーザの chroot は上記の上2つのパラメータで行うが、組み合わせで少し動作が異なるので以下に整理した。

    chroot_local_user chroot_list_enable 動 作 概 要
    NO NO デフォルトの設定であるが、ログイン時は当該ユーザのホームディレクトリ(/home/oyaji)にアクセスするが、その後は、全てのディレクトリにアクセスできてしまう。書き換えは無理でもほとんどのファイルにアクセスは可能になってしまうので、ローカルユーザ使用をした時点でここの設定変更は必須である。
    YES NO この設定ではログイン時は「/」にアクセスし、システムのディレクトリ全てが見えてしまうので、この設定は有り得ない。(bin ディレクトリ以外はアクセスはできないが)
    NO YES この設定では、ユーザを1行づつ記述したリスト(デフォルトは/etc/vsftpd/chroot_list。 chroot_list_file=/xxx/xx オプションでファイルは変更可。)に記載されているユーザのみ chroot され、当該ユーザのホームディレクトリ(/home/oyaji)配下しかアクセスできないが、未記載のユーザは、ログイン時は当該ユーザのホームディレクトリ(/home/oyaji)にアクセスするが、その後は、全てのディレクトリにアクセスできてしまう。
    YES YES この設定が、一番安全で間違いのない設定である。上記と異なるのは、基本的にローカルユーザはchrootされホームディレクトリ(/home/oyaji)配下しかアクセスできないが、/etc/vsftpd/chroot_list に記載されたユーザのみが全てのディレクトリにアクセスできるようになるので、意識して設定しない限り自由なアクセスができないので安全である。但し、特権ユーザがいなくても、空でもいいので /etc/vsftpd/chroot_list を用意しておかないと一切ログインできないので注意が必要である。

     なお、chroot すると /home/user 以下が root ディレクトリとなるので、Maildir 等のシステム関係のディレクトリやファイルまでが見えてしまい、誤操作でおかしくしてしまう可能性もある。ProFTPd と同様に以下のように設定を追加し、一般ユーザは public_html 以下しかアクセスできないようにするほうが良い。

    local_root=public_html

  12. ドットファイル表示の設定

    force_dot_files=NO (デフォルト:NO)

    vsftpd ではデフォルトで .htaccess のようなドットファイルは表示されない。必要なら本オプションをYES とすればよい。

  13. ログ関係の設定

    xferlog_enable=YES (デフォルト:NO)
    xferlog_std_format=YES (デフォルト:NO)
    log_ftp_protocol=NO (デフォルト:NO)
    vsftpd_log_file=/var/log/vsftpd.log (デフォルト:/var/log/vsftpd.log)
    xferlog_file=/var/log/xferlog (デフォルト:/var/log/xferlog)
    dual_log_enable=YES (デフォルト:NO)

    vsftpd_log_file
     
    vsftpd では、デフォルトでvsftpd オリジナルのログ(/var/log/vsftpd.log)が作成される。名称や場所を変更したければここで変更する。

    xferlog_enable
     
    本設定をYESとすると、アップロードやダウンロードの詳細ログが採られ、ログはvsftpd オリジナルのログ(/var/log/vsftpd.log)に作成される。

    xferlog_std_format
     
    本設定をYESとすると、ログフォーマットがwu-ftpd 相当のフォーマットになり、mrtg 等でログ解析が可能となる。このとき、ログファイルは:/var/log/xferlogとして作成される。

    xferlog_file
     
    xferlog の場所や名称を変更する場合に設定する。

    dual_log_enable
     
    本設定をYESとすると、vsftpd オリジナルのログとwu-ftpd 相当のフォーマットのログの両方を採取可能となる。

    log_ftp_protocol
     
    本設定をYESとすると、全てのやりとりをログに残すようになる。xferlog_std_formatとは背反なので、本設定をYES とした場合は、xferlog_std_format はNO とすること。デバック用だが、アタック監視に使えなくもないか?

  14. 時刻表示の変更

    use_localtime=YES (デフォルト:NO)

    時刻表示はデフォルトでGMTになっており、日本を対象にするなら上記設定を追加することにより、local timeに変更される。

  15. Standaloneモードの設定

    listen=NO (デフォルト:NO)

    Standaloneモードで動作させる場合の設定でありvsftpdのデフォルトはNOであるが、RedHat系はStandaloneモードがデフォルトなのでconfファイルの設定はYESとなっている。ここではinetdモードで起動するので、NOに変更する。

  16. anonymousFTPの停止

    anonymous_enable=NO (デフォルト:YES)

    anonymousFTPは、デフォルトで有効になっているので、運用しない場合は明示的に設定する必要がある。

◆anonymous関係の設定

ここでは、anonymousFTP を動作させる場合の代表的な設定をあげておきます。

  1. anonymousFTPの有効化

    anonymous_enable=YES (デフォルト:YES)

    vsftpd ではデフォルトでanonymousFTPが有効になっているので、敢えて設定は不要ではあるが、自分の意志でデフォルトで使用しているという意味で、この手の場合もおやじは極力設定を書くようにしている。何かあっても書いてあれば忘れないですし。

  2. anonymous でのアップロードの許可

    anon_upload_enable=YES (デフォルト:NO)

    おやじは恐ろしくてやる気はないが、どうしてもanonymous でアップロードさせたいときは、本オプションを YES にする。同時に write_enable もYES になっていないと機能しないので注意が必要である。
    なお、anonymous ログイン時の root ディレクトリは ftp ユーザのホームディレクトリ ( /srv/ftp ) であるが、ここにはパーミッションの関係で upload はできないのでこの配下に upload 専用ディレクトリ ( /srv/ftp/upload 等) を作成し、オーナをftp 、パーミッションを755 として書き込みできるようにする必要がある。

  3. anonymous の umask設定

    anon_umask=022 (デフォルト:077)

    デフォルトは077であり、このままだとファイル作成時のパーミションが600となり、upload したファイルは download できない。これを 022 とすれば、パーミションが644となり、ダンロード可となる。upload の使い方に合わせて設定する。

  4. anonymous での新規ディレクトリ作成

    anon_mkdir_write_enable=YES (デフォルト:NO)

    本オプションを YES とすると、anonymous ユーザでも新規にディレクトリを作成できる。但し、当然、write_enable になっていなければ駄目だし、親ディレクトリのパーミッションの整合もとれている必要がある。実質、upload ディレクトリ配下のみが対象か?

    anon_other_write_enable オプションでは削除やリネームもできるようになるが、事故のもとなので設定は不要(NO)と思う。

  5. anonymous の速度制限

    anon_max_rate=50000 (デフォルト:0 無制限)

    本オプションでanonymous クライアントの最大転送速度を指定できる。単位はByte/秒である。デフォルトは無制限なのでCPUパワーに余裕があれば、FTTHでも回線帯域を使い切ってしまうことがあるので、他サービスの影響を考えると制限したほうが良い。

■PASVモードでのNATルータ越えのインターネット公開

バージョン2.0.4以降は、pasv_addr_resolve オプションで デーモン起動時に pasv_address で指定されたホスト名を検索して得たIPアドレスをクライアントに通知できるようになりました。従って、動的IPアドレスのサービスでも、ルータのWAN 側のグローバルアドレスを牽けるホスト名を指定し、inetdモードで動作させればPASV未対応のルータでも問題なくPASVでFTPサーバを公開できます。本項の設定は不要です。

NAT ルータ配下で FTP サーバを PASV モードで公開するにはいくつか条件があり(こちらを参照)、 vsftpd はある程度対応できるようになっていますが、残念ながら固定 IP 環境でないとすんなりとは対応できません。 つまり vsftpd では、PASV コマンドの応答でクライアントに返送するサーバの IP アドレスを指定できるので、ここに ルータのWAN 側のグローバルアドレスを指定してあげれば、データコネクションの設定が問題なくでき通信も正常にできるようになっています。しかし、動的 IP の場合は運用中に当然アドレスが変化するので、conf ファイルでスタティックに設定しておくわけにはいきません。従って、WarFTPd の時と同様にスクリプトを使用して IP アドレスの変化を検出し、強制的に conf ファイルの設定を変更することで対処することにしました。(ProFTPd では、この設定にドメイン名が使用できるので、自サイトのグローバルアドレスが登録されている DDNS のドメインを指定しておけば、IP アドレスが変化しても追従できるので何も問題は発生しない.。)
おやじが使ったスクリプトは下記のようなもので、WarFTPD 用のものをモディファイしたものです。これを cron で5分ごとにでも動作させればアドレスが変化した時に自動的に vsftpd.conf の 「pasv_address」オプションのアドレスを変更してくれます。なお、本スクリプトを動作させると、「pasv_address」オプションがなかったり、形式がおかしい場合は強制的に作成してしまうので注意してください。
おやじが実際に導入する場合、Zive の DDNS 更新用スクリプトでDDNS の更新をしていますので、わざわざ別に動作させる必要はないのと連動性を考えれば、これにマージするか、こちらからコールするようにすると思います。

[使用方法]

  1. 下記スクリプトを /usr/local/bin 配下に vsftpd.cgi として設置し、実行権(755)を付与する。(755) 場所や名称は適当に。

  2. 最低限、パラメータの $host を自サイトの環境に合わせる。ここの設定値は、サーバ機で nslookup/dig  したときにルータの WAN 側のグローバルアドレスが牽ける自局のホスト名を設定する。おやじの場合、内向き DNS で example.zive.net は家庭内プライベートアドレスになるので、このため専用のホスト名を頂き、FTP 専用で exampleftp.zive.net というホスト名を使用している。
    なお、一応ログをとるようにしているので、$log_dir で指定したログ用のデイレクトリを作成する。
     現在は、自宅DDNSでの運用に切り替えたので、この目的専用のホスト名を内向きのゾーンにDDNSで登録し、そのアドレスを指定してある。(DNSとしては内向きだが、あるホスト名だけは動的IPアドレスが牽けるようにしてあり、これで対処している。)

  3. 後は、crontab に 5分後とに起動するよう設定するだけである。/etc/crontab に以下のように追加する。

    00-59/5 * * * * root /usr/bin/perl /usr/local/bin/vsftpd.cgi

#!/usr/bin/perl

# vsftpd.cgi is for updating automatically the address (pasv_address)
# which vsftpd advertises as a response of the PASV command.
# vsftpd.cgi is only for linuxor Linux.
# vsftpd.cgi v1.0 (by oyaji) 2004.06.06

########## パラメータ ##########
$host        = "exampleftp.zive.net"; # 自局ホストアドレス(FQDN)
$log_dir     = "/var/log/vsftpd/";  # ログディレクトリ
$debug       = 0;                   # デバッグ用詳細ログ(0/1=No/Yes)
$logcnt      = 50;                  # 最大ログ数

######## 変数(変更不可) ########
$vsftpd_conf = "/etc/vsftpd.conf";  # vsftpd.confへのパス
use Socket; # Socket モジュールを使う
########## メイン処理 ########## # ホスト名からIPアドレスへ変換 $iaddr = gethostbyname("$host"); if (! $iaddr) {&slog("IPアドレスが取得できません。"); exit;} # XX.XX.XX.XX形式に変換 $new_ip = join('.', unpack("C*", $iaddr)); # アドレス範囲チェック(プライベート含む) if ($new_ip eq "0.0.0.0") {&slog("IPアドレスが取得できません。"); exit;} if (($new_ip =~ m/^127./) || ($new_ip =~ m/^10./) || ($new_ip =~ m/^192.168./)) {&err; exit;} if ($new_ip =~ m/^172.(\d+)/) {if (($1 ge 16) && ($1 lt 32)){&err; exit;}} # アドレス変化? $mm = 1; $buf = ''; open(IN, "$vsftpd_conf"); @xx = <IN>; foreach $yy (@xx) { if ($yy =~ /^pasv_address=/) { if ($yy =~ /^pasv_address=(\d+.\d+.\d+.\d+)/) { if ($new_ip ne $1) {$mm = 2;} # option形式正常、アドレス変化 else{$mm = 0;} # option形式正常、アドレス変化なし }else{$mm = 2;} # option形式異常 if($mm ==2){ $yy = "pasv_address=$new_ip"; } } $buf .= $yy; } close(IN); if ($mm) { # IPアドレスが変化 if($mm == 1){$buf .= "pasv_address=$new_ip";} # option なし。追加。 open(OUT, "> $vsftpd_conf"); print(OUT "$buf\n"); # vsftpd.conf書き換え close(OUT); &slog(); # ログ出力 } ### ログ出力 ### sub slog { ($err) = @_; return unless defined $log_dir; @time = localtime(time()); $ptime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $time[5]+=1900, $time[4]+=1, $time[3], $time[2], $time[1], $time[0]); $dir =~ s/([^\/])$/$1\//; $file = $log_dir . "vsftpd.log"; $cnt = 0; $prtbuf = ""; open (LOG, "$file"); while ($zz = <LOG>) { $cnt++; } close(LOG); open (LOG,"$file"); while ($zz = <LOG>) { if ($cnt lt $logcnt) { $prtbuf .= "$zz"; } $cnt--; } close(LOG); if ($err) {if (! $debug) {return;} else {$prtbuf .= "$ptime $err";} } else {$prtbuf .= "$ptime IPアドレスが $new_ip に変わりました。";} open (LOG,"> $file"); print LOG "$prtbuf\n"; close(LOG); } sub err { &slog("IPアドレス($new_ip)が異常です。"); }

■起動設定

RedHat系の場合は、standaloneモードの起動スクリプトもインストールされるので、一応起動しないように止めます。(実際は、起動まではしてないはずです。)その後、下記によりxinetd 用起動設定ファイル(/etc/xinetd.d/vsftpd)を開いて disable を no に変更し、システム起動時にxinetd 経由で起動される設定変更し、chkconfig でその内容を確認した後、xinetd をrestart して起動します。

# /etc/init.d/vsftpd stop
# chkconfig vsftpd off
#
vi /etc/xinetd.d/vsftpd

# default: off
# description: The vsftpd FTP server serves FTP connections. It uses \
# normal, unencrypted usernames and passwords for authentication.
service ftp
{
      socket_type    = stream
      wait           = no
      user           = root
      server         = /usr/sbin/vsftpd
      server_args    = /etc/vsftpd/vsftpd.conf
      nice           = 10
      disable        = no
      flags          = IPv4
}

[Esc][:][w][q]で保存。

# chkconfig --list vsftpd
xinetd based services:
       vsftpd:         on
# /etc/init.d/xinetd restart



Top Pageへ