.. program:: nghttpx nghttpx - HTTP/2 proxy - HOW-TO =============================== :doc:`nghttpx.1` is a proxy translating protocols between HTTP/2 and other protocols (e.g., HTTP/1, SPDY). It operates in several modes and each mode may require additional programs to work with. This article describes each operation mode and explains the intended use-cases. It also covers some useful options later. Default mode ------------ If nghttpx is invoked without :option:`--http2-proxy`, it operates in default mode. In this mode, it works as reverse proxy (gateway) for both HTTP/2 and HTTP/1 clients to backend servers. This is also known as "HTTP/2 router". If nghttpx is linked with spdylay library and frontend connection is SSL/TLS, the frontend also supports SPDY protocol. By default, frontend connection is encrypted using SSL/TLS. So server's private key and certificate must be supplied to the command line (or through configuration file). In this case, the frontend protocol selection will be done via ALPN or NPN. To turn off encryption on frontend connection, use ``no-tls`` keyword in :option:`--frontend` option. In this case, SPDY protocol is not available even if spdylay library is liked to nghttpx. HTTP/2 and HTTP/1 are available on the frontend, and an HTTP/1 connection can be upgraded to HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by sending HTTP/2 connection preface is also supported. nghttpx can listen on multiple frontend addresses. This is achieved by using multiple :option:`--frontend` options. For each frontend address, TLS can be enabled or disabled. By default, backend connections are not encrypted. To enable TLS encryption on backend connections, use ``tls`` keyword in :option:`--backend` option. Using patterns and ``proto`` keyword in :option:`--backend` option, backend application protocol can be specified per host/request path pattern. It means that you can use both HTTP/2 and HTTP/1 in backend connections at the same time. Note that default backend protocol is HTTP/1.1. To use HTTP/2 in backend, you have to specify ``h2`` in ``proto`` keyword in :option:`--backend` explicitly. The backend is supposed to be Web server. For example, to make nghttpx listen to encrypted HTTP/2 requests at port 8443, and a backend Web server is configured to listen to HTTP request at port 8080 in the same host, run nghttpx command-line like this: .. code-block:: text $ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For example, you can send GET request to the server using nghttp: .. code-block:: text $ nghttp -nv https://localhost:8443/ HTTP/2 proxy mode ----------------- If nghttpx is invoked with :option:`--http2-proxy` (or its shorthand :option:`-s`) option, it operates in HTTP/2 proxy mode. The supported protocols in frontend and backend connections are the same in `default mode`_. The difference is that this mode acts like forward proxy and assumes the backend is HTTP proxy server (e.g., Squid, Apache Traffic Server). HTTP/1 request must include absolute URI in request line. By default, frontend connection is encrypted. So this mode is also called secure proxy. If nghttpx is linked with spdylay, it supports SPDY protocols and it works as so called SPDY proxy. To turn off encryption on frontend connection, use ``no-tls`` keyword in :option:`--frontend` option. The backend must be HTTP proxy server. nghttpx supports multiple backend server addresses. It translates incoming requests to HTTP request to backend server. The backend server performs real proxy work for each request, for example, dispatching requests to the origin server and caching contents. The backend connection is not encrypted by default. To enable encryption, use ``tls`` keyword in :option:`--backend` option. The default backend protocol is HTTP/1.1. To use HTTP/2 in backend connection, use :option:`--backend` option, and specify ``h2`` in ``proto`` keyword explicitly. For example, to make nghttpx listen to encrypted HTTP/2 requests at port 8443, and a backend HTTP proxy server is configured to listen to HTTP/1 request at port 8080 in the same host, run nghttpx command-line like this: .. code-block:: text $ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt At the time of this writing, Firefox 41 and Chromium v46 can use nghttpx as HTTP/2 proxy. To make Firefox or Chromium use nghttpx as HTTP/2 or SPDY proxy, user has to create proxy.pac script file like this: .. code-block:: javascript function FindProxyForURL(url, host) { return "HTTPS SERVERADDR:PORT"; } ``SERVERADDR`` and ``PORT`` is the hostname/address and port of the machine nghttpx is running. Please note that both Firefox and Chromium require valid certificate for secure proxy. For Firefox, open Preference window and select Advanced then click Network tab. Clicking Connection Settings button will show the dialog. Select "Automatic proxy configuration URL" and enter the path to proxy.pac file, something like this: .. code-block:: text file:///path/to/proxy.pac For Chromium, use following command-line: .. code-block:: text $ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn As HTTP/1 proxy server, Squid may work as out-of-box. Traffic server requires to be configured as forward proxy. Here is the minimum configuration items to edit: .. code-block:: text CONFIG proxy.config.reverse_proxy.enabled INT 0 CONFIG proxy.config.url_remap.remap_required INT 0 Consult Traffic server `documentation `_ to know how to configure traffic server as forward proxy and its security implications. ALPN support ------------ ALPN support requires OpenSSL >= 1.0.2. Disable frontend SSL/TLS ------------------------ The frontend connections are encrypted with SSL/TLS by default. To turn off SSL/TLS, use ``no-tls`` keyword in :option:`--frontend` option. If this option is used, the private key and certificate are not required to run nghttpx. Enable backend SSL/TLS ---------------------- The backend connections are not encrypted by default. To enable SSL/TLS encryption, use ``tls`` keyword in :option:`--backend` option. Enable SSL/TLS on memcached connection -------------------------------------- By default, memcached connection is not encrypted. To enable encryption, use ``tls`` keyword in :option:`--tls-ticket-key-memcached` for TLS ticket key, and :option:`--tls-session-cache-memcached` for TLS session cache. Specifying additional server certificates ----------------------------------------- nghttpx accepts additional server private key and certificate pairs using :option:`--subcert` option. It can be used multiple times. Specifying additional CA certificate ------------------------------------ By default, nghttpx tries to read CA certificate from system. But depending on the system you use, this may fail or is not supported. To specify CA certificate manually, use :option:`--cacert` option. The specified file must be PEM format and can contain multiple certificates. By default, nghttpx validates server's certificate. If you want to turn off this validation, knowing this is really insecure and what you are doing, you can use :option:`--insecure` option to disable certificate validation. Read/write rate limit --------------------- nghttpx supports transfer rate limiting on frontend connections. You can do rate limit per frontend connection for reading and writing individually. To perform rate limit for reading, use :option:`--read-rate` and :option:`--read-burst` options. For writing, use :option:`--write-rate` and :option:`--write-burst`. Please note that rate limit is performed on top of TCP and nothing to do with HTTP/2 flow control. Rewriting location header field ------------------------------- nghttpx automatically rewrites location response header field if the following all conditions satisfy: * URI in location header field is not absolute URI or is not https URI. * URI in location header field includes non empty host component. * host (without port) in URI in location header field must match the host appearing in :authority or host header field. When rewrite happens, URI scheme and port are replaced with the ones used in frontend, and host is replaced with which appears in :authority or host request header field. :authority header field has precedence. If the above conditions are not met with the host value in :authority header field, rewrite is retried with the value in host header field. Hot swapping ------------ nghttpx supports hot swapping using signals. The hot swapping in nghttpx is multi step process. First send USR2 signal to nghttpx process. It will do fork and execute new executable, using same command-line arguments and environment variables. At this point, both current and new processes can accept requests. To gracefully shutdown current process, send QUIT signal to current nghttpx process. When all existing frontend connections are done, the current process will exit. At this point, only new nghttpx process exists and serves incoming requests. Re-opening log files -------------------- When rotating log files, it is desirable to re-open log files after log rotation daemon renamed existing log files. To tell nghttpx to re-open log files, send USR1 signal to nghttpx process. It will re-open files specified by :option:`--accesslog-file` and :option:`--errorlog-file` options. Multiple frontend addresses --------------------------- nghttpx can listen on multiple frontend addresses. To specify them, just use :option:`--frontend` (or its shorthand :option:`-f`) option repeatedly. TLS can be enabled or disabled per frontend address basis. For example, to listen on port 443 with TLS enabled, and on port 80 without TLS: .. code-block:: text frontend=*,443 frontend=*,80;no-tls Multiple backend addresses -------------------------- nghttpx supports multiple backend addresses. To specify them, just use :option:`--backend` (or its shorthand :option:`-b`) option repeatedly. For example, to use ``192.168.0.10:8080`` and ``192.168.0.11:8080``, use command-line like this: ``-b192.168.0.10,8080 -b192.168.0.11,8080``. In configuration file, this looks like: .. code-block:: text backend=192.168.0.10,8080 backend=192.168.0.11,8008 nghttpx can route request to different backend according to request host and path. For example, to route request destined to host ``doc.example.com`` to backend server ``docserv:3000``, you can write like so: .. code-block:: text backend=docserv,3000;doc.example.com/ When you write this option in command-line, you should enclose argument with single or double quotes, since the character ``;`` has a special meaning in shell. To route, request to request path whose prefix is ``/foo`` to backend server ``[::1]:8080``, you can write like so: .. code-block:: text backend=::1,8080;/foo Of course, you can specify both host and request path at the same time: .. code-block:: text backend=192.168.0.10,8080;example.com/foo We can use ``*`` in the left most position of host to achieve wildcard suffix match. If ``*`` is the left most character, then the remaining string should match the request host suffix. ``*`` must match at least one character. For example, ``*.example.com`` matches ``www.example.com`` and ``dev.example.com``, and does not match ``example.com`` and ``nghttp2.org``. The exact match (without ``*``) always takes precedence over wildcard match. One important thing you have to remember is that we have to specify default routing pattern for so called "catch all" pattern. To write "catch all" pattern, just specify backend server address, without pattern. Usually, host is the value of ``Host`` header field. In HTTP/2, the value of ``:authority`` pseudo header field is used. When you write multiple backend addresses sharing the same routing pattern, they are used as load balancing. For example, to use 2 servers ``serv1:3000`` and ``serv2:3000`` for request host ``example.com`` and path ``/myservice``, you can write like so: .. code-block:: text backend=serv1,3000;example.com/myservice backend=serv2,3000;example.com/myservice You can also specify backend application protocol in :option:`--backend` option using ``proto`` keyword after pattern. Utilizing this allows ngttpx to route certain request to HTTP/2, other requests to HTTP/1. For example, to route requests to ``/ws/`` in backend HTTP/1.1 connection, and use backend HTTP/2 for other requests, do this: .. code-block:: text backend=serv1,3000;/;proto=h2 backend=serv1,3000;/ws/;proto=http/1.1 Note that the backends share the same pattern must have the same backend protocol. The default backend protocol is HTTP/1.1. TLS can be enabed per pattern basis: .. code-block:: text backend=serv1,8443;/;proto=h2;tls backend=serv2,8080;/ws/;proto=http/1.1 In the above case, connection to serv1 will be encrypted by TLS. On the other hand, connection to serv2 will not be encrypted by TLS. Migration from nghttpx v1.8.0 or earlier ---------------------------------------- As of nghttpx 1.9.0, ``--frontend-no-tls`` and ``--backend-no-tls`` have been removed. To disable encryption on frontend connection, use ``no-tls`` keyword in :option:`--frontend` potion: .. code-block:: text frontend=*,3000;no-tls The TLS encryption is now disabled on backend connection in all modes by default. To enable encryption on backend connection, use ``tls`` keyword in :option:`--backend` option: .. code-block:: text backend=127.0.0.1,8080;tls As of nghttpx 1.9.0, ``--http2-bridge``, ``--client`` and ``--client-proxy`` options have been removed. These functionality can be used using combinations of options. Use following option instead of ``--http2-bridge``: .. code-block:: text backend=,;;proto=h2;tls Use following options instead of ``--client``: .. code-block:: text frontend=,;no-tls backend=,;;proto=h2;tls Use following options instead of ``--client-proxy``: .. code-block:: text http2-proxy=yes frontend=,;no-tls backend=,;;proto=h2;tls We also removed ``--backend-http2-connections-per-worker`` option. It was present because previously the number of backend h2 connection was statically configured, and defaulted to 1. Now the number of backend h2 connection is increased on demand. We know the maximum number of concurrent streams per connection. When we push as many request as the maximum concurrency to the one connection, we create another new connection so that we can distribute load and avoid delay the request processing. This is done automatically without any configuration.