Apache に関する投稿を表示しています

htpasswdをちゃんと使う

なんだか htpasswd で長いパスワードを設定してもちゃんと機能していないっぽい…、いやいや Basic 認証だから短い文字列しか使えない、なんていう制約はない、のでは…?ということで調べた。結果、ドキュメントかコマンドのヘルプ表示に書いてあることがすべてだった。

まずは、おや??と思ったサーバが使っていたのが Apache 2.2 だったので、そちらのドキュメントを見てみる。

htpasswd - Manage user files for basic authentication - Apache HTTP Server Version 2.2

-m
Use MD5 encryption for passwords. This is the default (since version 2.2.18).

-d
Use crypt() encryption for passwords. This is not supported by the httpd server on Windows and Netware and TPF.
This algorithm limits the password length to 8 characters. This algorithm is insecure by today's standards. It used to be the default algorithm until version 2.2.17.

ち、ちしきもソフトウェアも更新されていない。。。
古い httpd を使っていたので、そのまま更新してパスワードファイルを作り直し。

後述するがデフォルトになっている MD5 を利用するのがいいっぽい。

$ sudo yum update httpd

$ htpasswd -inm foo-user

ついでに Apache 2.4 を使っている別サーバの様子も確認。

htpasswd - Manage user files for basic authentication - Apache HTTP Server Version 2.4

こちらは bcrypt が使えたり SHA が insecure だよといった情報も増えている。

-m
Use MD5 encryption for passwords. This is the default (since version 2.2.18).

-B
Use bcrypt encryption for passwords. This is currently considered to be very secure.

-C
This flag is only allowed in combination with -B (bcrypt encryption). It sets the computing time used for the bcrypt algorithm (higher is more secure but slower default: 5 valid: 4 to 17).

-d
Use crypt() encryption for passwords. This is not supported by the httpd server on Windows and Netware. This algorithm limits the password length to 8 characters. This algorithm is insecure by today's standards. It used to be the default algorithm until version 2.2.17.

-s
Use SHA encryption for passwords. Facilitates migration from/to Netscape servers using the LDAP Directory Interchange Format (ldif). This algorithm is insecure by today's standards.

なんで SHA が insecure なのかは下の Security Considerations トピックに書いてある。
SHA を指定するとパスワードに対してソルトが設定されず毎回同じ値になるのがよろしくないとのこと。

というわけでこちらの Apache 2.4 がいるサーバでは bcrypt を使う、ついでにコストパラメータもちょっと上げてみる。

$ htpasswd -nb -C 10 bar-user
...

実際に各種作って比べるとこんな感じ。
いままでのそれよりだいぶ雰囲気がちがう。。。

$ cat htpasswd_test.sh
#!/bin/sh

password=test-foo-bar

echo 'raw'
echo $password | htpasswd -inp test
echo 'crypt()'
echo $password | htpasswd -ind test
echo 'sha'
echo $password | htpasswd -ins test
echo 'md5'
echo $password | htpasswd -inm test
echo 'bcrypt()'
echo $password | htpasswd -inB test
echo 'bcrypt() with cost=10'
echo $password | htpasswd -inB -C 10 test


$ htpasswd_test.sh

raw
Warning: storing passwords as plain text might just not work on this platform.
test:test-foo-bar

crypt()
Warning: Password truncated to 8 characters by CRYPT algorithm.
test:19KcNn65a0Ovo

sha
test:{SHA}FsxBAWUFKrRlyJof3T+q9X6QfNE=

md5
test:$apr1$/nZjVA4i$5.tcV5puEwC6t0xQzuBfK1

bcrypt()
test:$2y$05$W4354fiJgesqn4/EXJhOsemadtHoX.PevbZA76fptomx09NAvbQTa

bcrypt() with cost=10
test:$2y$10$A6DDhPBzUOQA3aRui6acK.IaRpe0bqL9m5dcER4Gp0Bwk/SzEYhNa

Apache 2.4 で WebSocket もリバースプロキシする

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

Apache 2.4 で WebSocket をプロキシしたい。以前書いた docker-compose のフロントとして Apache を立てると、バックエンドで WebSocket を使う場合にすこしの設定を足す必要がある。

docker-compose で LDAP 認証のリバースプロキシを設定する | ごみばこいん Blog

nginx 使えよって話、めっちゃわかる。そのうちやる…たぶん…

ちなみに Apache 2.2 だとパッチがいたりするそうなので、がんばって!って感じっぽい。

 

httpd.conf あるいはその手の Apache 設定ファイルで以下のような設定を足すと良い。

# ...略...

# WebSocket をプロキシするモジュールを読み込み
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so


# ...略...


# 例えば Jupyter の場合はこんなパスをプロキシしてあげる

# websocket
ProxyPass /api/kernels/ ws://${REVERSE_PROXY}/api/kernels/
ProxyPassReverse /api/kernels/ ws://${REVERSE_PROXY}/api/kernels/

ProxyPass /terminals/websocket/ ws://${REVERSE_PROXY}/terminals/websocket/
ProxyPassReverse /terminals/websocket/ ws://${REVERSE_PROXY}/terminals/websocket/

# http
ProxyPass / http://${REVERSE_PROXY}/
ProxyPassReverse / http://${REVERSE_PROXY}/

 

REVERSE_PROXY は環境変数で、バックエンド( Jupyter )のホスト(とポート)を指定する。ぼくの手元のやつは docker-compose を使ってるのでこんな感じに書いている。

version: "3"

services:
  jupyter:
    container_name: "${APP_NAME}_jupyter"
    build: ./docker-jupyter
    command: start-notebook.sh --NotebookApp.token=''
    volumes:
      - ./notebooks:/home/jovyan/work
    environment:
      GRANT_SUDO: 1
      NB_UID: ${NB_UID}
      NB_GID: ${NB_GID}
  proxy:
    container_name: "${APP_NAME}_proxy"
    build: ./docker-proxy
    ports:
      - "${HTTP_PORT}:80"
    links:
      - jupyter:jupyter
    environment:
      REVERSE_PROXY: jupyter:8888

httpd:alpine の Docker イメージを利用しても WebSocket のプロキシが出来るので、そんな感じ。
いじょ

docker-compose で LDAP 認証のリバースプロキシを設定する

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

色々が色々あって、社内限定ツールに Active Directory を参照した LDAP 認証を掛けることがある。
それ自体は別にいいのだが Docker を使ってペペッと作って展開するといったときがやや面倒になった。

ので、それを docker-compose を使ってリバースプロキシを作ったら解決できたよ、というメモ。

 

こんな感じで docker-compose.yml を作って。

version: "2"

services:
  application:
    container_name: "${APP_NAME}_application"
    build: ./docker-app
    volumes:
      - ./src:/var/www/html
  proxy:
    container_name: "${APP_NAME}_proxy"
    build: ./docker-proxy
    ports:
      - "${HTTP_PORT}:80"
    links:
      - application:application

docker-compose をやったことがある人はご存知と思うが、このときの ${APP_NAME} や ${HTTP_PORT} は環境変数を指していて .env ファイルなどを作り APP_NAME=hogehoge みたいなことをしたらいい。

余談なのだけど、ドキュメントみたら version 3 のフォーマットがいつの間にかリリースされていて(しらなかった!!)、そっちに移行していく流れのほうがいいよねって思った。
Compose file version 3 reference | Docker Documentation

 

こんな感じで ./docker-proxy/Dockerfile を作って。

FROM httpd:alpine
COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf

 

こんな感じで ./docker-proxy/httpd.conf を作って。

# default configures
ServerRoot "/usr/local/apache2"
Listen 80
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so

<IfModule unixd_module>
    User daemon
    Group daemon
</IfModule>

ServerAdmin you@example.com
ServerName localhost:80

<Directory />
    AllowOverride none
    Require all denied
</Directory>

DocumentRoot "/usr/local/apache2/htdocs"

<Files ".ht*">
    Require all denied
</Files>

ErrorLog /proc/self/fd/2
LogLevel warn

<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog /proc/self/fd/1 common
</IfModule>

<IfModule mime_module>
    TypesConfig conf/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
</IfModule>

<IfModule ssl_module>
    SSLRandomSeed startup builtin
    SSLRandomSeed connect builtin
</IfModule>



# Load modules
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule auth_basic_module modules/mod_auth_basic.so

LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule ldap_module modules/mod_ldap.so

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so


# LDAP
LDAPTrustedMode SSL
LDAPVerifyServerCert off


# Proxy
<VirtualHost *:80>
    ProxyRequests Off
    ProxyPreserveHost Off
    AllowEncodedSlashes On
    KeepAlive Off

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    <Location />
        AuthName "Basic Auth"
        AuthType Basic
        AuthBasicProvider ldap
        AuthLDAPURL [ここにLDAPを参照するのURI]
        Require valid-user
    </Location>

    RequestHeader unset Authorization

    ProxyPass / http://application/
    ProxyPassReverse / http://application/
</VirtualHost>

 

あとは docker-compose up -d --build などと実行したら出来上がる。

$ docker-compose up -d --build

 

Apache をつかっている理由としては nginx の場合は公式イメージの中で LDAP のモジュールが提供されていないこと、組み込む場合にビルドが必要なことがあげられる。 Apache のイメージであればデフォルトで LDAP のモジュールが提供されている。さらに言えば
alpine イメージでも提供されているので debian ベースなイメージなどと比べて、軽量で高速上げ下げ出来たりしてめっちゃ良いよねってところもあった。調べると debian ベースにビルドしてるものもあって、良いんだけどう~~ん。

まあ「docker nginx ldap proxy」とか普通のワードで調べたらイメージだったり Dockerfile だったりが出てくるので、そのあたりを使ってもよかったのかもしれない。

debian ベースで nginx 1.11.13 をビルドする。 PR したらマージされる感あるのでバージョンアップもやっていけそう。
h3nrik/nginx-ldap - Docker Hub

debian ベースで nginx 1.9.9 をビルドする。2 年前から更新されていないので今後も更新されなさそう感
confirm/docker-nginx-ldap: nginx Docker image with ldap support

nginx 公式なのだけど nginx で LDAP ではなく、横にいる LDAP してくれるやつがよろしくやる、というものでちょっと違うかも。
nginxinc/nginx-ldap-auth: Example of LDAP authentication using ngx_http_auth_request_module

あるいは nginx-proxy っていうめっちゃ便利なリバースプロキシできる君があるので、これをベースに LDAP 認証のモジュールを追加するっていうのが、お手軽楽ちんで一番いいかもしれない。
jwilder/nginx-proxy: Automated nginx proxy for Docker containers using docker-gen

 

とりあえず一旦のところは Apache でやったよっていう話と、 nginx でも調べたら出てくるよ、ってまとめでおわり。