ファイル転送サーバ
Flexisip http file transfer server
ApacheコンテナとPHP-FPMコンテナからファイル転送サーバを構築
Apache httpd コンテナイメージ
Apache + PHP-FPM
Apache HTTP Server - ArchWiki
Apache httpd設定ファイル
/etc/httpd/conf/httpd.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
<FilesMatch \.php$>
SetHandler "proxy:fcgi://192.xx.xx.xx:9000"
</FilesMatch>
TLS認証方法(参考)
Two authentication methods are supported:
- TLS authentication: allows to accept or refuse a request based on a potential client certificate.
- Digest authentication: checks the password of the sender by using a password database (see Digest Access Authentication).
注)PHPでダイジェスト認証するため、以下のApacheモジュールは不要。
Apacheでproxy_fcgi を使用している場合、特定のHTTPヘッダー(例えば、Authorization ヘッダー)がPHP-FPMに正しく渡されないことがあります。これを解決するためには、SetEnvIf ディレクティブやProxyPass オプションを使用してヘッダーを適切に渡す設定を行う必要があります。
( BearerトークンやBasic認証のヘッダーをPHPで取得したい場合)
1. SetEnvIfディレクティブの使用
<VirtualHost *:80>
ServerName your-domain.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Require all granted
</Directory>
# Set up the environment variable for the Authorization header
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
# Proxy settings
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php/php-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
2. ProxyPassオプションの使用
<VirtualHost *:80>
ServerName your-domain.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Require all granted
</Directory>
# Pass Authorization header to PHP-FPM
<Proxy "unix:/var/run/php/php-fpm.sock|fcgi://localhost">
ProxySet env=Authorization
</Proxy>
# Proxy settings
ProxyPassMatch ^/(.*\.php(/.*)?)$ "unix:/var/run/php/php-fpm.sock|fcgi://localhost/$1"
</VirtualHost>
3. RewriteRuleを使用する方法(mod_rewrite)
<VirtualHost *:80>
ServerName your-domain.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Require all granted
</Directory>
# Enable rewrite engine
RewriteEngine On
# Capture the Authorization header and pass it as an environment variable
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [E=HTTP_AUTHORIZATION:%1]
# Proxy settings
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php/php-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
phpinfo()で下記変数の有無を確認
$_SERVER['HTTP_AUTHORIZATION']
Final Modification to run the flexisip file transfer server
Note) File Transfer Server php codes designed with Apache(required apace http header variables), so need to access it directly, not via proxy(nginx) .
1. apache folder
-
1-1: Replace apache folder
-
1-2: Edit the below line in apache/extra/httpd-ssl.conf to meet with your condition
ServerName xxx.xxxxxx.com
<IfModule proxy_module>
<FilesMatch "\.php$">
SetHandler "proxy:fcgi://10.xx.xx.1:9000"
</FilesMatch>
</IfModule>
SSLCertificateFile "/etc/letsencrypt/live/xxx.xxxxxx.com/fullchain.pem"
SSLCertificateKeyFile "/etc/letsencrypt/live/xxx.xxxxxx.com/privkey.pem"
2. nginx folder
- 2-1: Change file name of
ft.conf to deactivate it: like ft.conf.old, or delete it.
3. hft_conf folder(new)
-
3-1: For security reason, make hft_conf folder
and move hft_conf/flexisip-http-file-transfer-server.conf into this folder.
-
3-2: define the below lines in hft_conf/flexisip-http-file-transfer-server.conf
define("DIGEST_AUTH", true);
Note) default: false, if true, more secure but usability degrade. To upload a log file from linphone, it set to false.
define("AUTH_DB_HOST", "xxx.xxx.xxx.xx");
define("AUTH_DB_USER", "xxxxxx");
define("AUTH_DB_PASSWORD", "xxxxxxxxxxxxxxxx");
define("AUTH_DB_NAME", "xxxxxx");
define("ACCOUNTS_DB_TABLE", "accounts");
define("ACCOUNTS_ALGO_DB_TABLE", "passwords");
define("USE_PERSISTENT_CONNECTIONS", False);
define("AUTH_REALM", "sip.xxxxxxx.com");
define("AUTH_NONCE_KEY", "xxxxxxxxxxxxxx");
! Maybe, no need
define("PROXY_SELF_DOMAIN", "xxx.xxxxx.com");
4. docker-compose.yml
Reconfirm the below sections
-
4-1: nginx volumes section
volumes:
# nginx config
- ./nginx:/etc/nginx/conf.d
- /etc/letsencrypt:/etc/letsencrypt
- ./flexisip-account-manager/flexiapi:/var/www/html/flexiapi
-
4-2: apache port and volumes section
ports:
- 8080:8080
- 8443:8443
Note) Define the same directory for sharing between apache and ubuntu-flexisip containers. —> If not, occurs “file not found”
volumes:
# apache config
- ./apache/httpd_ft.conf:/usr/local/apache2/conf/httpd.conf
- ./apache/extra/httpd-ssl.conf:/usr/local/apache2/conf/extra/httpd-ssl.conf
- /etc/letsencrypt:/etc/letsencrypt
# for file transfer
- ./hft:/opt/belledonne-communications/share/flexisip-http-file-transfer-server
- ./hft-tmp:/var/opt/belledonne-communications/flexisip-http-file-transfer-tmp
- ./hft_conf/flexisip-http-file-transfer-server.conf:/etc/flexisip-http-file-transfer-server/flexisip-http-file-transfer-server.conf
# Flexisip-account-manager file transfer log
- ./log/flexisip-http-file-transfer-server.log:/var/opt/belledonne-communications/log/flexisip-http-file-transfer-server.log
-
4-3: ubuntu-flexisip volumes section
Note) Define the same directory for sharing between apache and ubuntu-flexisip containers. —> If not, occurs “file not found”
volumes:
- /etc/letsencrypt:/etc/letsencrypt
# previously need to add "flexisip" directory and input "flexisip.conf" into it.
- ./flexisip_conf:/etc/flexisip
# for conference server linphone db directory
- ./linphone:/root/.local/share/linphone
# for laravel php framework
- ./flexisip-account-manager/flexiapi:/var/www/html/flexiapi
# provisioning default config
- ./xmlrpc:/opt/belledonne-communications/share/flexisip-account-manager/xmlrpc
# for file transfer
- ./hft:/opt/belledonne-communications/share/flexisip-http-file-transfer-server
- ./hft-tmp:/var/opt/belledonne-communications/flexisip-http-file-transfer-tmp
- ./hft_conf/flexisip-http-file-transfer-server.conf:/etc/flexisip-http-file-transfer-server/flexisip-http-file-transfer-server.conf
# Flexisip-account-manager log
- ./log/flexisip-pusher.log:/var/opt/belledonne-communications/log/flexisip/flexisip-pusher.log
# Flexisip-account-manager file transfer log
- ./log/flexisip-http-file-transfer-server.log:/var/opt/belledonne-communications/log/flexisip-http-file-transfer-server.log
# php-fpm listen port config file
- ./php-fpm_conf/www.conf:/etc/php/8.1/fpm/pool.d/www.conf
- ./php-fpm_conf/php.ini:/etc/php/8.1/fpm/php.ini
参考)
Nginxでダイジェスト認証する場合の設定例
http {
server {
listen 80;
location / {
# バックエンドサーバーへのプロキシ設定
proxy_pass http://backend_server;
# 必要なヘッダーをバックエンドに渡す設定
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Authorizationヘッダーを渡す設定
proxy_set_header Authorization $http_authorization;
# 以下はオプションですが、一般的に使われるヘッダーの設定
proxy_set_header Accept-Encoding "";
proxy_set_header Connection "";
}
}
}
キャッシュを利用している場合
http {
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
server {
listen 80;
location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization $http_authorization;
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
# 認証ヘッダーが存在する場合にキャッシュをバイパス
proxy_cache_bypass $http_authorization;
# 認証ヘッダーが存在する場合にキャッシュからのレスポンスを無効化
proxy_no_cache $http_authorization;
}
}
}
Apache ProxyPassMatchによるfcgiの実行例
<VirtualHost *:80>
ServerName www.example.com
# FastCGIプロキシの設定
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/path/to/webroot/$1
# 必要なモジュールの読み込み
LoadModule headers_module modules/mod_headers.so
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
# キャッシュの設定
CacheRoot "/path/to/cache"
CacheEnable disk "/"
CacheDirLevels 2
CacheDirLength 1
<Directory "/path/to/webroot">
# 認証ヘッダーがある場合にキャッシュを無効にする設定
SetEnvIf Authorization "(.*)" noauth
Header set Cache-Control "no-store" env=noauth
CacheDisable "noauth"
</Directory>
</VirtualHost>
Conferenceサーバの設定
デバックモードで起動
docker compose ファイル内のubuntu-flexisip の cmd オプションで "--server proxy" を指定してproxy のみを起動してから、コンテナubuntu-flexisip 内で下記サーバのいずれかを --debug オプションを指定して起動。各サーバの動作を確認。
# /opt/belledonne-communications/bin/flexisip --server conference --debug
注) どちらのポート(5065, 6064) も外部(インターネット)に開放する必要はありません。
注) [conference-server], [b2bua-server]の outbound-proxy のSIPアドレスを、[global]セクションのtransportsに必ず追加すること。
[conference-server], [b2bua-server]
outbound-proxy=sip:127.0.0.1:7902;transport=tcp
[global]
transports=sip:127.0.0.1:7902;transport=tcp …
[conference-server]
enabled=true
transport=sip:127.0.0.1:6064;transport=tcp
# For chat conference:conference-factory, For audio/video conference :videoconference-factory
conference-factory-uris=sip:[email protected] sip:[email protected]
conference-focus-uris=sip:[email protected] sip:[email protected]
outbound-proxy=sip:127.0.0.1:5060;transport=tcp
local-domains=sip.example.com example.com
database-backend=mysql
database-connection-string=db=xxxxxxx user=xxxxxxx password=xxxxxxxx host=xx.xx.xx.xx
# Whether the conference server shall check device capabilities
# before inviting them to a session.
# The capability check is currently limited to Linphone client that
# put a +org.linphone.specs contact parameter in order to indicate
# whether they support group chat and secured group chat.
# Default: true
check-capabilities=false
# List of media supported by the conference server.
# Valid values are: audio, video and text. For example:
# supported-media-types=audio video text
# Default: text
supported-media-types=audio video text
# The preferred encryption the conference server will offer in the
# outgoing transactions.
# Valid values are: none, sdes, zrtp and dtls.
# Default: none
encryption=none
# Whether the conference server will delete chat rooms that have
# no participants registered.
#
# Default: true
empty-chat-room-deletion=true
# Directory where the conference server state files are stored.
#
# Default: /var/opt/belledonne-communications/lib/flexisip
state-directory=/var/opt/belledonne-communications/lib/flexisip
注) 一つのSIPドメインに対し、conference-factory-uris, conference-focus-uris には、それぞれ2つのURIを指定していますが、Linphoneの設定で会議用URIとビデオ・オーディオ会議用URIを同一にすれば、2つ目のURIは削除できます。
ファイル転送サーバ:トラブルシュート
ダウンロードエラー
Ingress-NGINXなどのリバースプロキシでTLS終端を行うと、バックエンドのApacheサーバではリクエストがHTTPとして処理されます。これにより、PHPアプリケーションが生成するファイルのダウンロードURLが http:// となり、LinphoneなどHTTPSを必須とするクライアントではダウンロード(401エラー)に失敗します。これは、クライアント側がHTTPSを要求している一方で、サーバがHTTP URLを返してしまうという不整合によって発生する問題です。
hft.php
修正前
$prefix = (isset($_SERVER["HTTPS"]) && strtolower($_SERVER["HTTPS"]) == "on") ? "https" : "http";
$start = $prefix . "://" . $ipport . ':' . $_SERVER['SERVER_PORT'] . dirname($_SERVER['REQUEST_URI']);
$http_url = $start . "/tmp/" . basename($uploadfile); // file will be served in the ./tmp/ directory on the server path
修正案A:HTTPSでのみアクセスする場合
SERVER_PORT → HTTP_X_FORWARDED_PORT へ変更
$prefix = (isset($_SERVER["HTTPS"]) && strtolower($_SERVER["HTTPS"]) == "on") ? "https" : "http";
$start = $prefix . "://" . $ipport . ':' . $_SERVER['HTTP_X_FORWARDED_PORT'] . dirname($_SERVER['REQUEST_URI']);
$http_url = $start . "/tmp/" . basename($uploadfile); // file will be served in the ./tmp/ directory on the server path
注)nginxの設定ファイルで明示的に以下を記述
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Authorization $http_authorization;
注)Apacheの設定ファイルで以下を追加
<IfModule setenvif_module>
SetEnvIf X-Forwarded-Proto "https" HTTPS=on
# Set up the environment variable for the Authorization header
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</IfModule>
修正案B:HTTPまたはHTTPSでアクセスする場合
$prefix = (isset($_SERVER["HTTPS"]) && strtolower($_SERVER["HTTPS"]) == "on" || isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && strtolower($_SERVER["HTTP_X_FORWARDED_PROTO"]) == "https") ? "https" : "http";
$serverport = $_SERVER['HTTP_X_FORWARDED_PORT'] ?? $_SERVER['SERVER_PORT'];
$start = $prefix . "://" . $ipport . ':' . $serverport . dirname($_SERVER['REQUEST_URI']);
$http_url = $start . "/tmp/" . basename($uploadfile); // file will be served in the ./tmp/ directory on the server path
注)HTTP_***などのヘッダー環境変数はphpinfo()で確認すること。
サイズ制限
アップロードするファイルサイズはphp.iniとnginxの設定で決まります。
/etc/nginx/default.conf
client_max_body_size 100M;
/usr/local/etc/php/php.ini
upload_max_filesize = 50M
post_max_size = 100M