nginx
mustache
synology

SynoloryNASに自分用プロキシサーバを構築する

前提

DS1815+(DSM 6)の環境です。
SynologyNASは通常環境ですとポート80、ポート443がNAS自身のプロキシサーバでListenされています。しかしどのサービスもそれらのポートを使用していません。
これらを開放して、Docker内にプロキシサーバを構築するまでをメモします。

手順

ポート開放

SynologyNAS(DSM 6)のプロキシサーバはnginxで構成されています。
大抵のサービスはWeb上で管理を行うため、プロキシサーバはとても重要な機能なので、その設定にはガードが掛けられています。
実際の/etc/nginx/nginx.confは電源投入時やDMSの設定変更時に随時/usr/syno/share/nginx/nginx.mustacheから構築されなおします。

/usr/syno/share/nginx/nginx.mustache
# Copyright (c) 2000-2016 Synology Inc. All rights reserved.

worker_processes        auto;
#worker_cpu_affinity    auto;
worker_rlimit_nofile    65535;

include conf.d/main.conf;

events {
    use             epoll;
    multi_accept    on;
    accept_mutex    off;
    worker_connections {{DSM.worker_connections}};

    include conf.d/events.conf;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  off;
    #access_log syslog:server=unix:/dev/log,facility=local7,tag=nginx_access,nohostname main;
    error_log   syslog:server=unix:/dev/log,facility=local7,tag=nginx_error,nohostname error;

    sendfile        on;
    server_tokens   off;

    proxy_request_buffering     off;
    fastcgi_request_buffering   off;
    scgi_request_buffering      off;

    proxy_buffering     off;
    fastcgi_buffering   off;
    scgi_buffering      off;

    resolver_timeout              5s;
    client_header_timeout         10s;
    client_body_timeout           60s;
    send_timeout                  60s;
    keepalive_timeout             65s 20s;
    client_max_body_size          0;
    server_names_hash_max_size    8192;

    ssl_certificate           /usr/syno/etc/certificate/system/default/fullchain.pem;
    ssl_certificate_key       /usr/syno/etc/certificate/system/default/privkey.pem;
    ssl_protocols             {{SSLProfile.protocols}};
    ssl_ciphers               {{SSLProfile.ciphersuite}};
    ssl_dhparam               {{SSLProfile.dhparam}};
    ssl_prefer_server_ciphers on;

    ssl_session_tickets       off;
    ssl_session_cache         shared:SSL:1m;
    ssl_session_timeout       3600s;

    server_tag     {{#DSM.server_tag}}"{{.}}"{{/DSM.server_tag}}{{^DSM.server_tag}}off{{/DSM.server_tag}};

    {{> /usr/syno/share/nginx/gzip}}

    upstream synoscgi {
        server unix:/run/synoscgi.sock;
    }

    index index.html index.htm index.php;

    set_real_ip_from 127.0.0.1;
    real_ip_header X-Real-IP;

    {{> /usr/syno/share/nginx/DSM}}
    {{> /usr/syno/share/nginx/WWWService}}

    include conf.d/http.*.conf;
    include app.d/server.*.conf;
    include sites-enabled/*;
}

これがファイル全体です。奇妙は記述ですがmustacheという記法で書かれています。ポート80,443がListenされているのは{{> /usr/syno/share/nginx/WWWService}}の中なので、この行を削除して再起動すればポート80と443は解放されます。

Dockerにリバースプロキシを立てる

普通にDockerコンテナを作って立ち上げれば大丈夫です。
但し、Dockerアプリの管理画面からローカルポートに80や443を設定するとエラーになり設定できません。
解決策は2つ。
1.Dockerアプリに頼らず自分でサービス化する。
2.Dockerアプリの制限を突破する

1が普通ですが、Dockerでサーバを追加するたびにサービス化を書くのは面倒くさいです。
DocerアプリはNASの再起動時とかにも勝手に立ち上げてくれるなど便利ですので、2の「Dockerアプリの制限を突破する」を採用します。

Dockerアプリの設定ファイルを編集する

/var/packages/Docker/etc/の下に[コンテナ名].configというjsonファイルがあり、これがコンテナの設定になっています。ローカルポートを適当に3080と3443とつけて登録した後、コンテナを停止するとよいでしょう。
その後下記ファイルの3080と3443を80と443に書き換えればOKです。

/var/packages/Docker/etc/proxy1.config
{
    "cap_add": [], 
    "cap_drop": [], 
    "cmd": "", 
    "cpu_priority": 0, 
    "ddsm_bind_share": "", 
    "devices": [], 
    "enable_publish_all_ports": false, 
    "enable_restart_policy": true, 
    "enabled": true, 
    "env_variables": [], 
    "exporting": false, 
    "id": "70sldkafjaslkdfjsakldfjsdklfjaslkjladkfjaldkf446", 
    "image": "proxy:latest", 
    "is_ddsm": false, 
    "is_package": false, 
    "links": [], 
    "memory_limit": 0, 
    "name": "proxy1", 
    "network": [
        {
            "driver": "", 
            "name": "proxy"
        }
    ], 
    "port_bindings": [
        {
            "container_port": 80, 
            "host_port": 3080, 
            "type": "tcp"
        }, 
        {
            "container_port": 443, 
            "fixed": false, 
            "host_port": 3443, 
            "type": "tcp"
        }
    ], 
    "privileged": false, 
    "shortcut": {
        "enable_shortcut": false
    }, 
    "use_host_network": false, 
    "volume_bindings": [
        {
            "fixed": false, 
            "host_volume_file": "/homes/nak/app/proxy", 
            "mount_point": "/myapp", 
            "type": "rw"
        }
    ]
}

Dockerコンテナを起動する

普通にDockerアプリから起動すればポート80も443もproxyのものになっています。

最後に

synologyのプロキシにnginxが使われていると知ったときに、「このサーバを乗っ取ればいいのかな?」と思ったのですが、mustacheの記法に驚いてそのまま別に立てることにしました。

参考文献

Freeing up port 80 on Synology DSM