• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. program:: nghttpx
2
3nghttpx - HTTP/2 proxy - HOW-TO
4===============================
5
6:doc:`nghttpx.1` is a proxy translating protocols between HTTP/2 and
7other protocols (e.g., HTTP/1).  It operates in several modes and each
8mode may require additional programs to work with.  This article
9describes each operation mode and explains the intended use-cases.  It
10also covers some useful options later.
11
12Default mode
13------------
14
15If nghttpx is invoked without :option:`--http2-proxy`, it operates in
16default mode.  In this mode, it works as reverse proxy (gateway) for
17both HTTP/2 and HTTP/1 clients to backend servers.  This is also known
18as "HTTP/2 router".
19
20By default, frontend connection is encrypted using SSL/TLS.  So
21server's private key and certificate must be supplied to the command
22line (or through configuration file).  In this case, the frontend
23protocol selection will be done via ALPN or NPN.
24
25To turn off encryption on frontend connection, use ``no-tls`` keyword
26in :option:`--frontend` option.  HTTP/2 and HTTP/1 are available on
27the frontend, and an HTTP/1 connection can be upgraded to HTTP/2 using
28HTTP Upgrade.  Starting HTTP/2 connection by sending HTTP/2 connection
29preface is also supported.
30
31nghttpx can listen on multiple frontend addresses.  This is achieved
32by using multiple :option:`--frontend` options.  For each frontend
33address, TLS can be enabled or disabled.
34
35By default, backend connections are not encrypted.  To enable TLS
36encryption on backend connections, use ``tls`` keyword in
37:option:`--backend` option.  Using patterns and ``proto`` keyword in
38:option:`--backend` option, backend application protocol can be
39specified per host/request path pattern.  It means that you can use
40both HTTP/2 and HTTP/1 in backend connections at the same time.  Note
41that default backend protocol is HTTP/1.1.  To use HTTP/2 in backend,
42you have to specify ``h2`` in ``proto`` keyword in :option:`--backend`
43explicitly.
44
45The backend is supposed to be a Web server.  For example, to make
46nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
47backend Web server is configured to listen to HTTP requests at port
488080 on the same host, run nghttpx command-line like this:
49
50.. code-block:: text
51
52    $ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
53
54Then an HTTP/2 enabled client can access the nghttpx server using HTTP/2.  For
55example, you can send a GET request using nghttp:
56
57.. code-block:: text
58
59    $ nghttp -nv https://localhost:8443/
60
61HTTP/2 proxy mode
62-----------------
63
64If nghttpx is invoked with :option:`--http2-proxy` (or its shorthand
65:option:`-s`) option, it operates in HTTP/2 proxy mode.  The supported
66protocols in frontend and backend connections are the same as in `default
67mode`_.  The difference is that this mode acts like a forward proxy and
68assumes the backend is an HTTP proxy server (e.g., Squid, Apache Traffic
69Server).  HTTP/1 requests must include an absolute URI in request line.
70
71By default, the frontend connection is encrypted.  So this mode is
72also called secure proxy.
73
74To turn off encryption on the frontend connection, use ``no-tls`` keyword
75in :option:`--frontend` option.
76
77The backend must be an HTTP proxy server.  nghttpx supports multiple
78backend server addresses.  It translates incoming requests to HTTP
79request to backend server.  The backend server performs real proxy
80work for each request, for example, dispatching requests to the origin
81server and caching contents.
82
83The backend connection is not encrypted by default.  To enable
84encryption, use ``tls`` keyword in :option:`--backend` option.  The
85default backend protocol is HTTP/1.1.  To use HTTP/2 in backend
86connection, use :option:`--backend` option, and specify ``h2`` in
87``proto`` keyword explicitly.
88
89For example, to make nghttpx listen to encrypted HTTP/2 requests at
90port 8443, and a backend HTTP proxy server is configured to listen to
91HTTP/1 requests at port 8080 on the same host, run nghttpx command-line
92like this:
93
94.. code-block:: text
95
96    $ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
97
98At the time of this writing, Firefox 41 and Chromium v46 can use
99nghttpx as HTTP/2 proxy.
100
101To make Firefox or Chromium use nghttpx as HTTP/2 proxy, user has to
102create proxy.pac script file like this:
103
104.. code-block:: javascript
105
106    function FindProxyForURL(url, host) {
107        return "HTTPS SERVERADDR:PORT";
108    }
109
110``SERVERADDR`` and ``PORT`` is the hostname/address and port of the
111machine nghttpx is running.  Please note that both Firefox and
112Chromium require valid certificate for secure proxy.
113
114For Firefox, open Preference window and select Advanced then click
115Network tab.  Clicking Connection Settings button will show the
116dialog.  Select "Automatic proxy configuration URL" and enter the path
117to proxy.pac file, something like this:
118
119.. code-block:: text
120
121    file:///path/to/proxy.pac
122
123For Chromium, use following command-line:
124
125.. code-block:: text
126
127    $ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
128
129As HTTP/1 proxy server, Squid may work as out-of-box.  Traffic server
130requires to be configured as forward proxy.  Here is the minimum
131configuration items to edit:
132
133.. code-block:: text
134
135    CONFIG proxy.config.reverse_proxy.enabled INT 0
136    CONFIG proxy.config.url_remap.remap_required INT 0
137
138Consult Traffic server `documentation
139<http://trafficserver.readthedocs.org/en/latest/admin-guide/configuration/transparent-forward-proxying.en.html>`_
140to know how to configure traffic server as forward proxy and its
141security implications.
142
143ALPN support
144------------
145
146ALPN support requires OpenSSL >= 1.0.2.
147
148Disable frontend SSL/TLS
149------------------------
150
151The frontend connections are encrypted with SSL/TLS by default.  To
152turn off SSL/TLS, use ``no-tls`` keyword in :option:`--frontend`
153option.  If this option is used, the private key and certificate are
154not required to run nghttpx.
155
156Enable backend SSL/TLS
157----------------------
158
159The backend connections are not encrypted by default.  To enable
160SSL/TLS encryption, use ``tls`` keyword in :option:`--backend` option.
161
162Enable SSL/TLS on memcached connection
163--------------------------------------
164
165By default, memcached connection is not encrypted.  To enable
166encryption, use ``tls`` keyword in
167:option:`--tls-ticket-key-memcached` for TLS ticket key, and
168:option:`--tls-session-cache-memcached` for TLS session cache.
169
170Specifying additional server certificates
171-----------------------------------------
172
173nghttpx accepts additional server private key and certificate pairs
174using :option:`--subcert` option.  It can be used multiple times.
175
176Specifying additional CA certificate
177------------------------------------
178
179By default, nghttpx tries to read CA certificate from system.  But
180depending on the system you use, this may fail or is not supported.
181To specify CA certificate manually, use :option:`--cacert` option.
182The specified file must be PEM format and can contain multiple
183certificates.
184
185By default, nghttpx validates server's certificate.  If you want to
186turn off this validation, knowing this is really insecure and what you
187are doing, you can use :option:`--insecure` option to disable
188certificate validation.
189
190Read/write rate limit
191---------------------
192
193nghttpx supports transfer rate limiting on frontend connections.  You
194can do rate limit per frontend connection for reading and writing
195individually.
196
197To perform rate limit for reading, use :option:`--read-rate` and
198:option:`--read-burst` options.  For writing, use
199:option:`--write-rate` and :option:`--write-burst`.
200
201Please note that rate limit is performed on top of TCP and nothing to
202do with HTTP/2 flow control.
203
204Rewriting location header field
205-------------------------------
206
207nghttpx automatically rewrites location response header field if the
208following all conditions satisfy:
209
210* In the default mode (:option:`--http2-proxy` is not used)
211* :option:`--no-location-rewrite` is not used
212* URI in location header field is an absolute URI
213* URI in location header field includes non empty host component.
214* host (without port) in URI in location header field must match the
215  host appearing in ``:authority`` or ``host`` header field.
216
217When rewrite happens, URI scheme is replaced with the ones used in
218frontend, and authority is replaced with which appears in
219``:authority``, or ``host`` request header field.  ``:authority``
220header field has precedence over ``host``.
221
222Hot swapping
223------------
224
225nghttpx supports hot swapping using signals.  The hot swapping in
226nghttpx is multi step process.  First send USR2 signal to nghttpx
227process.  It will do fork and execute new executable, using same
228command-line arguments and environment variables.
229
230As of nghttpx version 1.20.0, that is all you have to do.  The new
231master process sends QUIT signal to the original process, when it is
232ready to serve requests, to shut it down gracefully.
233
234For earlier versions of nghttpx, you have to do one more thing.  At
235this point, both current and new processes can accept requests.  To
236gracefully shutdown current process, send QUIT signal to current
237nghttpx process.  When all existing frontend connections are done, the
238current process will exit.  At this point, only new nghttpx process
239exists and serves incoming requests.
240
241If you want to just reload configuration file without executing new
242binary, send SIGHUP to nghttpx master process.
243
244Re-opening log files
245--------------------
246
247When rotating log files, it is desirable to re-open log files after
248log rotation daemon renamed existing log files.  To tell nghttpx to
249re-open log files, send USR1 signal to nghttpx process.  It will
250re-open files specified by :option:`--accesslog-file` and
251:option:`--errorlog-file` options.
252
253Multiple frontend addresses
254---------------------------
255
256nghttpx can listen on multiple frontend addresses.  To specify them,
257just use :option:`--frontend` (or its shorthand :option:`-f`) option
258repeatedly.  TLS can be enabled or disabled per frontend address
259basis.  For example, to listen on port 443 with TLS enabled, and on
260port 80 without TLS:
261
262.. code-block:: text
263
264   frontend=*,443
265   frontend=*,80;no-tls
266
267
268Multiple backend addresses
269--------------------------
270
271nghttpx supports multiple backend addresses.  To specify them, just
272use :option:`--backend` (or its shorthand :option:`-b`) option
273repeatedly.  For example, to use ``192.168.0.10:8080`` and
274``192.168.0.11:8080``, use command-line like this:
275``-b192.168.0.10,8080 -b192.168.0.11,8080``.  In configuration file,
276this looks like:
277
278.. code-block:: text
279
280   backend=192.168.0.10,8080
281   backend=192.168.0.11,8008
282
283nghttpx can route request to different backend according to request
284host and path.  For example, to route request destined to host
285``doc.example.com`` to backend server ``docserv:3000``, you can write
286like so:
287
288.. code-block:: text
289
290   backend=docserv,3000;doc.example.com/
291
292When you write this option in command-line, you should enclose
293argument with single or double quotes, since the character ``;`` has a
294special meaning in shell.
295
296To route, request to request path ``/foo`` to backend server
297``[::1]:8080``, you can write like so:
298
299.. code-block:: text
300
301   backend=::1,8080;/foo
302
303If the last character of path pattern is ``/``, all request paths
304which start with that pattern match:
305
306.. code-block:: text
307
308   backend=::1,8080;/bar/
309
310The request path ``/bar/buzz`` matches the ``/bar/``.
311
312You can use ``*`` at the end of the path pattern to make it wildcard
313pattern.  ``*`` must match at least one character:
314
315.. code-block:: text
316
317   backend=::1,8080;/sample*
318
319The request path ``/sample1/foo`` matches the ``/sample*`` pattern.
320
321Of course, you can specify both host and request path at the same
322time:
323
324.. code-block:: text
325
326   backend=192.168.0.10,8080;example.com/foo
327
328We can use ``*`` in the left most position of host to achieve wildcard
329suffix match.  If ``*`` is the left most character, then the remaining
330string should match the request host suffix.  ``*`` must match at
331least one character.  For example, ``*.example.com`` matches
332``www.example.com`` and ``dev.example.com``, and does not match
333``example.com`` and ``nghttp2.org``.  The exact match (without ``*``)
334always takes precedence over wildcard match.
335
336One important thing you have to remember is that we have to specify
337default routing pattern for so called "catch all" pattern.  To write
338"catch all" pattern, just specify backend server address, without
339pattern.
340
341Usually, host is the value of ``Host`` header field.  In HTTP/2, the
342value of ``:authority`` pseudo header field is used.
343
344When you write multiple backend addresses sharing the same routing
345pattern, they are used as load balancing.  For example, to use 2
346servers ``serv1:3000`` and ``serv2:3000`` for request host
347``example.com`` and path ``/myservice``, you can write like so:
348
349.. code-block:: text
350
351   backend=serv1,3000;example.com/myservice
352   backend=serv2,3000;example.com/myservice
353
354You can also specify backend application protocol in
355:option:`--backend` option using ``proto`` keyword after pattern.
356Utilizing this allows ngttpx to route certain request to HTTP/2, other
357requests to HTTP/1.  For example, to route requests to ``/ws/`` in
358backend HTTP/1.1 connection, and use backend HTTP/2 for other
359requests, do this:
360
361.. code-block:: text
362
363   backend=serv1,3000;/;proto=h2
364   backend=serv1,3000;/ws/;proto=http/1.1
365
366The default backend protocol is HTTP/1.1.
367
368TLS can be enabled per pattern basis:
369
370.. code-block:: text
371
372   backend=serv1,8443;/;proto=h2;tls
373   backend=serv2,8080;/ws/;proto=http/1.1
374
375In the above case, connection to serv1 will be encrypted by TLS.  On
376the other hand, connection to serv2 will not be encrypted by TLS.
377
378Dynamic hostname lookup
379-----------------------
380
381By default, nghttpx performs backend hostname lookup at start up, or
382configuration reload, and keeps using them in its entire session.  To
383make nghttpx perform hostname lookup dynamically, use ``dns``
384parameter in :option:`--backend` option, like so:
385
386.. code-block:: text
387
388   backend=foo.example.com,80;;dns
389
390nghttpx will cache resolved addresses for certain period of time.  To
391change this cache period, use :option:`--dns-cache-timeout`.
392
393Enable PROXY protocol
394---------------------
395
396PROXY protocol can be enabled per frontend.  In order to enable PROXY
397protocol, use ``proxyproto`` parameter in :option:`--frontend` option,
398like so:
399
400.. code-block:: text
401
402   frontend=*,443;proxyproto
403
404nghttpx supports both PROXY protocol v1 and v2.  AF_UNIX in PROXY
405protocol version 2 is ignored.
406
407Session affinity
408----------------
409
410Two kinds of session affinity are available: client IP, and HTTP
411Cookie.
412
413To enable client IP based affinity, specify ``affinity=ip`` parameter
414in :option:`--backend` option.  If PROXY protocol is enabled, then an
415address obtained from PROXY protocol is taken into consideration.
416
417To enable HTTP Cookie based affinity, specify ``affinity=cookie``
418parameter, and specify a name of cookie in ``affinity-cookie-name``
419parameter.  Optionally, a Path attribute can be specified in
420``affinity-cookie-path`` parameter:
421
422.. code-block:: text
423
424   backend=127.0.0.1,3000;;affinity=cookie;affinity-cookie-name=nghttpxlb;affinity-cookie-path=/
425
426Secure attribute of cookie is set if client connection is protected by
427TLS.
428
429PSK cipher suites
430-----------------
431
432nghttpx supports pre-shared key (PSK) cipher suites for both frontend
433and backend TLS connections.  For frontend connection, use
434:option:`--psk-secrets` option to specify a file which contains PSK
435identity and secrets.  The format of the file is
436``<identity>:<hex-secret>``, where ``<identity>`` is PSK identity, and
437``<hex-secret>`` is PSK secret in hex, like so:
438
439.. code-block:: text
440
441   client1:9567800e065e078085c241d54a01c6c3f24b3bab71a606600f4c6ad2c134f3b9
442   client2:b1376c3f8f6dcf7c886c5bdcceecd1e6f1d708622b6ddd21bda26ebd0c0bca99
443
444nghttpx server accepts any of the identity and secret pairs in the
445file.  The default cipher suite list does not contain PSK cipher
446suites.  In order to use PSK, PSK cipher suite must be enabled by
447using :option:`--ciphers` option.  The desired PSK cipher suite may be
448listed in `HTTP/2 cipher black list
449<https://tools.ietf.org/html/rfc7540#appendix-A>`_.  In order to use
450such PSK cipher suite with HTTP/2, disable HTTP/2 cipher black list by
451using :option:`--no-http2-cipher-black-list` option.  But you should
452understand its implications.
453
454At the time of writing, even if only PSK cipher suites are specified
455in :option:`--ciphers` option, certificate and private key are still
456required.
457
458For backend connection, use :option:`--client-psk-secrets` option to
459specify a file which contains single PSK identity and secret.  The
460format is the same as the file used by :option:`--psk-secrets`
461described above, but only first identity and secret pair is solely
462used, like so:
463
464.. code-block:: text
465
466   client2:b1376c3f8f6dcf7c886c5bdcceecd1e6f1d708622b6ddd21bda26ebd0c0bca99
467
468The default cipher suite list does not contain PSK cipher suites.  In
469order to use PSK, PSK cipher suite must be enabled by using
470:option:`--client-ciphers` option.  The desired PSK cipher suite may
471be listed in `HTTP/2 cipher black list
472<https://tools.ietf.org/html/rfc7540#appendix-A>`_.  In order to use
473such PSK cipher suite with HTTP/2, disable HTTP/2 cipher black list by
474using :option:`--client-no-http2-cipher-black-list` option.  But you
475should understand its implications.
476
477TLSv1.3
478-------
479
480As of nghttpx v1.34.0, if it is built with OpenSSL 1.1.1 or later, it
481supports TLSv1.3.  0-RTT data is supported, but by default its
482processing is postponed until TLS handshake completes to mitigate
483replay attack.  This costs extra round trip and reduces effectiveness
484of 0-RTT data.  :option:`--tls-no-postpone-early-data` makes nghttpx
485not wait for handshake to complete before forwarding request included
486in 0-RTT to get full potential of 0-RTT data.  In this case, nghttpx
487adds ``Early-Data: 1`` header field when forwarding a request to a
488backend server.  All backend servers should recognize this header
489field and understand that there is a risk for replay attack.  See `RFC
4908470 <https://tools.ietf.org/html/rfc8470>`_ for ``Early-Data`` header
491field.
492
493nghttpx disables anti replay protection provided by OpenSSL.  The anti
494replay protection of OpenSSL requires that a resumed request must hit
495the same server which generates the session ticket.  Therefore it
496might not work nicely in a deployment where there are multiple nghttpx
497instances sharing ticket encryption keys via memcached.
498
499Because TLSv1.3 completely changes the semantics of cipher suite
500naming scheme and structure, nghttpx provides the new option
501:option:`--tls13-ciphers` and :option:`--tls13-client-ciphers` to
502change preferred cipher list for TLSv1.3.
503
504WebSockets over HTTP/2
505----------------------
506
507nghttpx supports `RFC 8441 <https://tools.ietf.org/html/rfc8441>`_
508Bootstrapping WebSockets with HTTP/2 for both frontend and backend
509connections.  This feature is enabled by default and no configuration
510is required.
511
512Migration from nghttpx v1.18.x or earlier
513-----------------------------------------
514
515As of nghttpx v1.19.0, :option:`--ciphers` option only changes cipher
516list for frontend TLS connection.  In order to change cipher list for
517backend connection, use :option:`--client-ciphers` option.
518
519Similarly, :option:`--no-http2-cipher-black-list` option only disables
520HTTP/2 cipher black list for frontend connection.  In order to disable
521HTTP/2 cipher black list for backend connection, use
522:option:`--client-no-http2-cipher-black-list` option.
523
524``--accept-proxy-protocol`` option was deprecated.  Instead, use
525``proxyproto`` parameter in :option:`--frontend` option to enable
526PROXY protocol support per frontend.
527
528Migration from nghttpx v1.8.0 or earlier
529----------------------------------------
530
531As of nghttpx 1.9.0, ``--frontend-no-tls`` and ``--backend-no-tls``
532have been removed.
533
534To disable encryption on frontend connection, use ``no-tls`` keyword
535in :option:`--frontend` potion:
536
537.. code-block:: text
538
539   frontend=*,3000;no-tls
540
541The TLS encryption is now disabled on backend connection in all modes
542by default.  To enable encryption on backend connection, use ``tls``
543keyword in :option:`--backend` option:
544
545.. code-block:: text
546
547   backend=127.0.0.1,8080;tls
548
549As of nghttpx 1.9.0, ``--http2-bridge``, ``--client`` and
550``--client-proxy`` options have been removed.  These functionality can
551be used using combinations of options.
552
553Use following option instead of ``--http2-bridge``:
554
555.. code-block:: text
556
557   backend=<ADDR>,<PORT>;;proto=h2;tls
558
559Use following options instead of ``--client``:
560
561.. code-block:: text
562
563   frontend=<ADDR>,<PORT>;no-tls
564   backend=<ADDR>,<PORT>;;proto=h2;tls
565
566Use following options instead of ``--client-proxy``:
567
568.. code-block:: text
569
570   http2-proxy=yes
571   frontend=<ADDR>,<PORT>;no-tls
572   backend=<ADDR>,<PORT>;;proto=h2;tls
573
574We also removed ``--backend-http2-connections-per-worker`` option.  It
575was present because previously the number of backend h2 connection was
576statically configured, and defaulted to 1.  Now the number of backend
577h2 connection is increased on demand.  We know the maximum number of
578concurrent streams per connection.  When we push as many request as
579the maximum concurrency to the one connection, we create another new
580connection so that we can distribute load and avoid delay the request
581processing.  This is done automatically without any configuration.
582