1# Routers
2
3Connecting Requests to Services
4{: .subtitle }
5
6![routers](../../assets/img/routers.png)
7
8A router is in charge of connecting incoming requests to the services that can handle them.
9In the process, routers may use pieces of [middleware](../../middlewares/overview.md) to update the request,
10or act before forwarding the request to the service.
11
12## Configuration Example
13
14??? example "Requests /foo are Handled by service-foo -- Using the [File Provider](../../providers/file.md)"
15
16    ```yaml tab="YAML"
17    ## Dynamic configuration
18    http:
19      routers:
20        my-router:
21          rule: "Path(`/foo`)"
22          service: service-foo
23    ```
24
25    ```toml tab="TOML"
26    ## Dynamic configuration
27    [http.routers]
28      [http.routers.my-router]
29        rule = "Path(`/foo`)"
30        service = "service-foo"
31    ```
32
33??? example "Forwarding all (non-tls) requests on port 3306 to a database service"
34
35    **Dynamic Configuration**
36
37    ```yaml tab="File (YAML)"
38    ## Dynamic configuration
39    tcp:
40      routers:
41        to-database:
42          entryPoints:
43            - "mysql"
44          # Catch every request (only available rule for non-tls routers. See below.)
45          rule: "HostSNI(`*`)"
46          service: database
47    ```
48
49    ```toml tab="File (TOML)"
50    ## Dynamic configuration
51    [tcp]
52      [tcp.routers]
53        [tcp.routers.to-database]
54          entryPoints = ["mysql"]
55          # Catch every request (only available rule for non-tls routers. See below.)
56          rule = "HostSNI(`*`)"
57          service = "database"
58    ```
59
60    **Static Configuration**
61
62    ```yaml tab="File (YAML)"
63    ## Static configuration
64    entryPoints:
65      web:
66        address: ":80"
67      mysql:
68        address: ":3306"
69    ```
70
71    ```toml tab="File (TOML)"
72    ## Static configuration
73    [entryPoints]
74      [entryPoints.web]
75        address = ":80"
76      [entryPoints.mysql]
77        address = ":3306"
78    ```
79
80    ```bash tab="CLI"
81    ## Static configuration
82    --entryPoints.web.address=:80
83    --entryPoints.mysql.address=:3306
84    ```
85
86## Configuring HTTP Routers
87
88!!! warning "The character `@` is not authorized in the router name"
89
90### EntryPoints
91
92If not specified, HTTP routers will accept requests from all defined entry points.
93If you want to limit the router scope to a set of entry points, set the `entryPoints` option.
94
95??? example "Listens to Every EntryPoint"
96
97    **Dynamic Configuration**
98
99    ```yaml tab="File (YAML)"
100    ## Dynamic configuration
101    http:
102      routers:
103        Router-1:
104          # By default, routers listen to every entry points
105          rule: "Host(`example.com`)"
106          service: "service-1"
107    ```
108
109    ```toml tab="File (TOML)"
110    ## Dynamic configuration
111    [http.routers]
112      [http.routers.Router-1]
113        # By default, routers listen to every entry points
114        rule = "Host(`example.com`)"
115        service = "service-1"
116    ```
117
118    **Static Configuration**
119
120    ```yaml tab="File (YAML)"
121    ## Static configuration
122    entryPoints:
123      web:
124        address: ":80"
125      websecure:
126        address: ":443"
127      other:
128        address: ":9090"
129    ```
130
131    ```toml tab="File (TOML)"
132    ## Static configuration
133    [entryPoints]
134      [entryPoints.web]
135        address = ":80"
136      [entryPoints.websecure]
137        address = ":443"
138      [entryPoints.other]
139        address = ":9090"
140    ```
141
142    ```bash tab="CLI"
143    ## Static configuration
144    --entrypoints.web.address=:80
145    --entrypoints.websecure.address=:443
146    --entrypoints.other.address=:9090
147    ```
148
149??? example "Listens to Specific EntryPoints"
150
151    **Dynamic Configuration**
152
153    ```yaml tab="File (YAML)"
154    ## Dynamic configuration
155    http:
156      routers:
157        Router-1:
158          # won't listen to entry point web
159          entryPoints:
160            - "websecure"
161            - "other"
162          rule: "Host(`example.com`)"
163          service: "service-1"
164    ```
165
166    ```toml tab="File (TOML)"
167    ## Dynamic configuration
168    [http.routers]
169      [http.routers.Router-1]
170        # won't listen to entry point web
171        entryPoints = ["websecure", "other"]
172        rule = "Host(`example.com`)"
173        service = "service-1"
174    ```
175
176    **Static Configuration**
177
178    ```yaml tab="File (YAML)"
179    ## Static configuration
180    entryPoints:
181      web:
182        address: ":80"
183      websecure:
184        address: ":443"
185      other:
186        address: ":9090"
187    ```
188
189    ```toml tab="File (TOML)"
190    ## Static configuration
191    [entryPoints]
192      [entryPoints.web]
193        address = ":80"
194      [entryPoints.websecure]
195        address = ":443"
196      [entryPoints.other]
197        address = ":9090"
198    ```
199
200    ```bash tab="CLI"
201    ## Static configuration
202    --entrypoints.web.address=:80
203    --entrypoints.websecure.address=:443
204    --entrypoints.other.address=:9090
205    ```
206
207### Rule
208
209Rules are a set of matchers configured with values, that determine if a particular request matches specific criteria.
210If the rule is verified, the router becomes active, calls middlewares, and then forwards the request to the service.
211
212??? tip "Backticks or Quotes?"
213    To set the value of a rule, use [backticks](https://en.wiktionary.org/wiki/backtick) ``` ` ``` or escaped double-quotes `\"`.
214
215    Single quotes `'` are not accepted as values are [Golang's String Literals](https://golang.org/ref/spec#String_literals).
216
217!!! example "Host is example.com"
218
219    ```toml
220    rule = "Host(`example.com`)"
221    ```
222
223!!! example "Host is example.com OR Host is example.org AND path is /traefik"
224
225    ```toml
226    rule = "Host(`example.com`) || (Host(`example.org`) && Path(`/traefik`))"
227    ```
228
229The table below lists all the available matchers:
230
231| Rule                                                                   | Description                                                                                                    |
232|------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
233| ```Headers(`key`, `value`)```                                          | Check if there is a key `key`defined in the headers, with the value `value`                                    |
234| ```HeadersRegexp(`key`, `regexp`)```                                   | Check if there is a key `key`defined in the headers, with a value that matches the regular expression `regexp` |
235| ```Host(`example.com`, ...)```                                         | Check if the request domain (host header value) targets one of the given `domains`.                            |
236| ```HostHeader(`example.com`, ...)```                                   | Same as `Host`, only exists for historical reasons.                                                            |
237| ```HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)``` | Match the request domain. See "Regexp Syntax" below.                                                           |
238| ```Method(`GET`, ...)```                                               | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`)    |
239| ```Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...)```         | Match exact request path. See "Regexp Syntax" below.                                                           |
240| ```PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`)```   | Match request prefix path. See "Regexp Syntax" below.                                                          |
241| ```Query(`foo=bar`, `bar=baz`)```                                      | Match Query String parameters. It accepts a sequence of key=value pairs.                                       |
242| ```ClientIP(`10.0.0.0/16`, `::1`)```                                   | Match if the request client IP is one of the given IP/CIDR. It accepts IPv4, IPv6 and CIDR formats.            |
243
244!!! important "Non-ASCII Domain Names"
245
246    Non-ASCII characters are not supported in `Host` and `HostRegexp` expressions, and by doing so the associated router will be invalid.
247    For the `Host` expression, domain names containing non-ASCII characters must be provided as punycode encoded values ([rfc 3492](https://tools.ietf.org/html/rfc3492)).
248    As well, when using the `HostRegexp` expressions, in order to match domain names containing non-ASCII characters, the regular expression should match a punycode encoded domain name.
249
250!!! important "Regexp Syntax"
251
252    `HostRegexp`, `PathPrefix`, and `Path` accept an expression with zero or more groups enclosed by curly braces, which are called named regexps.
253    Named regexps, of the form `{name:regexp}`, are the only expressions considered for regexp matching.
254    The regexp name (`name` in the above example) is an arbitrary value, that exists only for historical reasons.
255
256    Any `regexp` supported by [Go's regexp package](https://golang.org/pkg/regexp/) may be used.
257
258!!! info "Combining Matchers Using Operators and Parenthesis"
259
260    You can combine multiple matchers using the AND (`&&`) and OR (`||`) operators. You can also use parenthesis.
261
262!!! info "Invert a matcher"
263
264    You can invert a matcher by using the `!` operator.
265
266!!! important "Rule, Middleware, and Services"
267
268    The rule is evaluated "before" any middleware has the opportunity to work, and "before" the request is forwarded to the service.
269
270!!! info "Path Vs PathPrefix"
271
272    Use `Path` if your service listens on the exact path only. For instance, `Path: /products` would match `/products` but not `/products/shoes`.
273
274    Use a `*Prefix*` matcher if your service listens on a particular base path but also serves requests on sub-paths.
275    For instance, `PathPrefix: /products` would match `/products` but also `/products/shoes` and `/products/shirts`.
276    Since the path is forwarded as-is, your service is expected to listen on `/products`.
277
278!!! info "ClientIP matcher"
279
280    The `ClientIP` matcher will only match the request client IP and does not use the `X-Forwarded-For` header for matching.
281
282### Priority
283
284To avoid path overlap, routes are sorted, by default, in descending order using rules length. The priority is directly equal to the length of the rule, and so the longest length has the highest priority.
285
286A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
287
288??? info "How default priorities are computed"
289
290    ```yaml tab="File (YAML)"
291    ## Dynamic configuration
292    http:
293      routers:
294        Router-1:
295          rule: "HostRegexp(`.*\.traefik\.com`)"
296          # ...
297        Router-2:
298          rule: "Host(`foobar.traefik.com`)"
299          # ...
300    ```
301
302    ```toml tab="File (TOML)"
303    ## Dynamic configuration
304    [http.routers]
305      [http.routers.Router-1]
306        rule = "HostRegexp(`.*\.traefik\.com`)"
307        # ...
308      [http.routers.Router-2]
309        rule = "Host(`foobar.traefik.com`)"
310        # ...
311    ```
312
313    In this case, all requests with host `foobar.traefik.com` will be routed through `Router-1` instead of `Router-2`.
314
315    | Name     | Rule                                 | Priority |
316    |----------|--------------------------------------|----------|
317    | Router-1 | ```HostRegexp(`.*\.traefik\.com`)``` | 30       |
318    | Router-2 | ```Host(`foobar.traefik.com`)```     | 26       |
319
320    The previous table shows that `Router-1` has a higher priority than `Router-2`.
321
322    To solve this issue, the priority must be set.
323
324??? example "Set priorities -- using the [File Provider](../../providers/file.md)"
325
326    ```yaml tab="File (YAML)"
327    ## Dynamic configuration
328    http:
329      routers:
330        Router-1:
331          rule: "HostRegexp(`.*\.traefik\.com`)"
332          entryPoints:
333          - "web"
334          service: service-1
335          priority: 1
336        Router-2:
337          rule: "Host(`foobar.traefik.com`)"
338          entryPoints:
339          - "web"
340          priority: 2
341          service: service-2
342    ```
343
344    ```toml tab="File (TOML)"
345    ## Dynamic configuration
346    [http.routers]
347      [http.routers.Router-1]
348        rule = "HostRegexp(`.*\.traefik\.com`)"
349        entryPoints = ["web"]
350        service = "service-1"
351        priority = 1
352      [http.routers.Router-2]
353        rule = "Host(`foobar.traefik.com`)"
354        entryPoints = ["web"]
355        priority = 2
356        service = "service-2"
357    ```
358
359    In this configuration, the priority is configured to allow `Router-2` to handle requests with the `foobar.traefik.com` host.
360
361### Middlewares
362
363You can attach a list of [middlewares](../../middlewares/overview.md) to each HTTP router.
364The middlewares will take effect only if the rule matches, and before forwarding the request to the service.
365
366!!! warning "The character `@` is not authorized in the middleware name."
367
368!!! tip "Middlewares order"
369
370    Middlewares are applied in the same order as their declaration in **router**.
371
372??? example "With a [middleware](../../middlewares/overview.md) -- using the [File Provider](../../providers/file.md)"
373
374    ```yaml tab="YAML"
375    ## Dynamic configuration
376    http:
377      routers:
378        my-router:
379          rule: "Path(`/foo`)"
380          # declared elsewhere
381          middlewares:
382          - authentication
383          service: service-foo
384    ```
385
386    ```toml tab="TOML"
387    ## Dynamic configuration
388    [http.routers]
389      [http.routers.my-router]
390        rule = "Path(`/foo`)"
391        # declared elsewhere
392        middlewares = ["authentication"]
393        service = "service-foo"
394    ```
395
396### Service
397
398Each request must eventually be handled by a [service](../services/index.md),
399which is why each router definition should include a service target,
400which is basically where the request will be passed along to.
401
402In general, a service assigned to a router should have been defined,
403but there are exceptions for label-based providers.
404See the specific [docker](../providers/docker.md#service-definition), [rancher](../providers/rancher.md#service-definition),
405or [marathon](../providers/marathon.md#service-definition) documentation.
406
407!!! warning "The character `@` is not authorized in the service name."
408
409!!! important "HTTP routers can only target HTTP services (not TCP services)."
410
411### TLS
412
413#### General
414
415 When a TLS section is specified, it instructs Traefik that the current router is dedicated to HTTPS requests only (and that the router should ignore HTTP (non TLS) requests).
416Traefik will terminate the SSL connections (meaning that it will send decrypted data to the services).
417
418??? example "Configuring the router to accept HTTPS requests only"
419
420    ```yaml tab="File (YAML)"
421    ## Dynamic configuration
422    http:
423      routers:
424        Router-1:
425          rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
426          service: service-id
427          # will terminate the TLS request
428          tls: {}
429    ```
430
431    ```toml tab="File (TOML)"
432    ## Dynamic configuration
433    [http.routers]
434      [http.routers.Router-1]
435        rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
436        service = "service-id"
437        # will terminate the TLS request
438        [http.routers.Router-1.tls]
439    ```
440
441!!! important "Routers for HTTP & HTTPS"
442
443    If you need to define the same route for both HTTP and HTTPS requests, you will need to define two different routers:
444    one with the tls section, one without.
445
446    ??? example "HTTP & HTTPS routes"
447
448        ```yaml tab="File (YAML)"
449        ## Dynamic configuration
450        http:
451          routers:
452            my-https-router:
453              rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
454              service: service-id
455              # will terminate the TLS request
456              tls: {}
457
458            my-http-router:
459              rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
460              service: service-id
461        ```
462
463        ```toml tab="File (TOML)"
464        ## Dynamic configuration
465        [http.routers]
466          [http.routers.my-https-router]
467            rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
468            service = "service-id"
469            # will terminate the TLS request
470            [http.routers.my-https-router.tls]
471
472          [http.routers.my-http-router]
473            rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
474            service = "service-id"
475        ```
476
477#### `options`
478
479The `options` field enables fine-grained control of the TLS parameters.
480It refers to a [TLS Options](../../https/tls.md#tls-options) and will be applied only if a `Host` rule is defined.
481
482!!! info "Server Name Association"
483
484    Even though one might get the impression that a TLS options reference is mapped to a router, or a router rule,
485    one should realize that it is actually mapped only to the host name found in the `Host` part of the rule.
486    Of course, there could also be several `Host` parts in a rule, in which case the TLS options reference would be mapped to as many host names.
487
488    Another thing to keep in mind is:
489    the TLS option is picked from the mapping mentioned above and based on the server name provided during the TLS handshake,
490    and it all happens before routing actually occurs.
491
492!!! info "Domain Fronting"
493
494    In the case of domain fronting,
495    if the TLS options associated with the Host Header and the SNI are different then Traefik will respond with a status code `421`.
496
497??? example "Configuring the TLS options"
498
499    ```yaml tab="File (YAML)"
500    ## Dynamic configuration
501    http:
502      routers:
503        Router-1:
504          rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
505          service: service-id
506          # will terminate the TLS request
507          tls:
508            options: foo
509
510    tls:
511      options:
512        foo:
513          minVersion: VersionTLS12
514          cipherSuites:
515            - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
516            - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
517            - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
518            - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
519            - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
520    ```
521
522    ```toml tab="File (TOML)"
523    ## Dynamic configuration
524    [http.routers]
525      [http.routers.Router-1]
526        rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
527        service = "service-id"
528        # will terminate the TLS request
529        [http.routers.Router-1.tls]
530          options = "foo"
531
532    [tls.options]
533      [tls.options.foo]
534        minVersion = "VersionTLS12"
535        cipherSuites = [
536          "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
537          "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
538          "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
539          "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
540          "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
541        ]
542    ```
543
544!!! important "Conflicting TLS Options"
545
546    Since a TLS options reference is mapped to a host name,
547    if a configuration introduces a situation where the same host name (from a `Host` rule) gets matched with two TLS options references,
548    a conflict occurs, such as in the example below:
549
550    ```yaml tab="File (YAML)"
551    ## Dynamic configuration
552    http:
553      routers:
554        routerfoo:
555          rule: "Host(`snitest.com`) && Path(`/foo`)"
556          tls:
557            options: foo
558
559        routerbar:
560          rule: "Host(`snitest.com`) && Path(`/bar`)"
561          tls:
562            options: bar
563    ```
564
565    ```toml tab="File (TOML)"
566    ## Dynamic configuration
567    [http.routers]
568      [http.routers.routerfoo]
569        rule = "Host(`snitest.com`) && Path(`/foo`)"
570        [http.routers.routerfoo.tls]
571          options = "foo"
572
573    [http.routers]
574      [http.routers.routerbar]
575        rule = "Host(`snitest.com`) && Path(`/bar`)"
576        [http.routers.routerbar.tls]
577          options = "bar"
578    ```
579
580    If that happens, both mappings are discarded, and the host name (`snitest.com` in this case) for these routers gets associated with the default TLS options instead.
581
582#### `certResolver`
583
584If `certResolver` is defined, Traefik will try to generate certificates based on routers `Host` & `HostSNI` rules.
585
586```yaml tab="File (YAML)"
587## Dynamic configuration
588http:
589  routers:
590    routerfoo:
591      rule: "Host(`snitest.com`) && Path(`/foo`)"
592      tls:
593        certResolver: foo
594```
595
596```toml tab="File (TOML)"
597## Dynamic configuration
598[http.routers]
599  [http.routers.routerfoo]
600    rule = "Host(`snitest.com`) && Path(`/foo`)"
601    [http.routers.routerfoo.tls]
602      certResolver = "foo"
603```
604
605!!! info "Multiple Hosts in a Rule"
606    The rule ```Host(`test1.example.com`,`test2.example.com`)``` will request a certificate with the main domain `test1.example.com` and SAN `test2.example.com`.
607
608#### `domains`
609
610You can set SANs (alternative domains) for each main domain.
611Every domain must have A/AAAA records pointing to Traefik.
612Each domain & SAN will lead to a certificate request.
613
614```yaml tab="File (YAML)"
615## Dynamic configuration
616http:
617  routers:
618    routerbar:
619      rule: "Host(`snitest.com`) && Path(`/bar`)"
620      tls:
621        certResolver: "bar"
622        domains:
623          - main: "snitest.com"
624            sans:
625              - "*.snitest.com"
626```
627
628```toml tab="File (TOML)"
629## Dynamic configuration
630[http.routers]
631  [http.routers.routerbar]
632    rule = "Host(`snitest.com`) && Path(`/bar`)"
633    [http.routers.routerbar.tls]
634      certResolver = "bar"
635      [[http.routers.routerbar.tls.domains]]
636        main = "snitest.com"
637        sans = ["*.snitest.com"]
638```
639
640[ACME v2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) supports wildcard certificates.
641As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605) wildcard certificates can only be generated through a [`DNS-01` challenge](../../https/acme.md#dnschallenge).
642
643Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 `DNS-01` challenges are executed.
644In this case the generated DNS TXT record for both domains is the same.
645Even though this behavior is [DNS RFC](https://community.letsencrypt.org/t/wildcard-issuance-two-txt-records-for-the-same-name/54528/2) compliant,
646it can lead to problems as all DNS providers keep DNS records cached for a given time (TTL) and this TTL can be greater than the challenge timeout making the `DNS-01` challenge fail.
647
648The Traefik ACME client library [lego](https://github.com/go-acme/lego) supports some but not all DNS providers to work around this issue.
649The [supported `provider` table](../../https/acme.md#providers) indicates if they allow generating certificates for a wildcard domain and its root domain.
650
651!!! important "Wildcard certificates can only be verified through a [`DNS-01` challenge](../../https/acme.md#dnschallenge)."
652
653!!! warning "Double Wildcard Certificates"
654    It is not possible to request a double wildcard certificate for a domain (for example `*.*.local.com`).
655
656## Configuring TCP Routers
657
658!!! warning "The character `@` is not authorized in the router name"
659
660### General
661
662If both HTTP routers and TCP routers listen to the same entry points, the TCP routers will apply *before* the HTTP routers.
663If no matching route is found for the TCP routers, then the HTTP routers will take over.
664
665### EntryPoints
666
667If not specified, TCP routers will accept requests from all defined entry points.
668If you want to limit the router scope to a set of entry points, set the entry points option.
669
670??? example "Listens to Every Entry Point"
671
672    **Dynamic Configuration**
673
674    ```yaml tab="File (YAML)"
675    ## Dynamic configuration
676
677    tcp:
678      routers:
679        Router-1:
680          # By default, routers listen to every entrypoints
681          rule: "HostSNI(`example.com`)"
682          service: "service-1"
683          # will route TLS requests (and ignore non tls requests)
684          tls: {}
685    ```
686
687    ```toml tab="File (TOML)"
688    ## Dynamic configuration
689
690    [tcp.routers]
691      [tcp.routers.Router-1]
692        # By default, routers listen to every entrypoints
693        rule = "HostSNI(`example.com`)"
694        service = "service-1"
695        # will route TLS requests (and ignore non tls requests)
696        [tcp.routers.Router-1.tls]
697    ```
698
699    **Static Configuration**
700
701    ```yaml tab="File (YAML)"
702    ## Static configuration
703
704    entryPoints:
705      web:
706        address: ":80"
707      websecure:
708        address: ":443"
709      other:
710        address: ":9090"
711    ```
712
713    ```toml tab="File (TOML)"
714    ## Static configuration
715
716    [entryPoints]
717      [entryPoints.web]
718        address = ":80"
719      [entryPoints.websecure]
720        address = ":443"
721      [entryPoints.other]
722        address = ":9090"
723    ```
724
725    ```bash tab="CLI"
726    ## Static configuration
727    --entrypoints.web.address=:80
728    --entrypoints.websecure.address=:443
729    --entrypoints.other.address=:9090
730    ```
731
732??? example "Listens to Specific Entry Points"
733
734    **Dynamic Configuration**
735
736    ```yaml tab="File (YAML)"
737    ## Dynamic configuration
738    tcp:
739      routers:
740        Router-1:
741          # won't listen to entry point web
742          entryPoints:
743            - "websecure"
744            - "other"
745          rule: "HostSNI(`example.com`)"
746          service: "service-1"
747          # will route TLS requests (and ignore non tls requests)
748          tls: {}
749    ```
750
751    ```toml tab="File (TOML)"
752    ## Dynamic configuration
753    [tcp.routers]
754      [tcp.routers.Router-1]
755        # won't listen to entry point web
756        entryPoints = ["websecure", "other"]
757        rule = "HostSNI(`example.com`)"
758        service = "service-1"
759        # will route TLS requests (and ignore non tls requests)
760        [tcp.routers.Router-1.tls]
761    ```
762
763    **Static Configuration**
764
765    ```yaml tab="File (YAML)"
766    ## Static configuration
767
768    entryPoints:
769      web:
770        address: ":80"
771      websecure:
772        address: ":443"
773      other:
774        address: ":9090"
775    ```
776
777    ```toml tab="File (TOML)"
778    ## Static configuration
779
780    [entryPoints]
781      [entryPoints.web]
782        address = ":80"
783      [entryPoints.websecure]
784        address = ":443"
785      [entryPoints.other]
786        address = ":9090"
787    ```
788
789    ```bash tab="CLI"
790    ## Static configuration
791    --entrypoints.web.address=:80
792    --entrypoints.websecure.address=:443
793    --entrypoints.other.address=:9090
794    ```
795
796### Rule
797
798| Rule                           | Description                                                             |
799|--------------------------------|-------------------------------------------------------------------------|
800| ```HostSNI(`domain-1`, ...)``` | Check if the Server Name Indication corresponds to the given `domains`. |
801
802!!! important "Non-ASCII Domain Names"
803
804    Non-ASCII characters are not supported in the `HostSNI` expression, and by doing so the associated TCP router will be invalid.
805    Domain names containing non-ASCII characters must be provided as punycode encoded values ([rfc 3492](https://tools.ietf.org/html/rfc3492)).
806
807!!! important "HostSNI & TLS"
808
809    It is important to note that the Server Name Indication is an extension of the TLS protocol.
810    Hence, only TLS routers will be able to specify a domain name with that rule.
811    However, non-TLS routers will have to explicitly use that rule with `*` (every domain) to state that every non-TLS request will be handled by the router.
812
813### Middlewares
814
815You can attach a list of [middlewares](../../middlewares/overview.md) to each TCP router.
816The middlewares will take effect only if the rule matches, and before connecting to the service.
817
818!!! warning "The character `@` is not allowed to be used in the middleware name."
819
820!!! tip "Middlewares order"
821
822    Middlewares are applied in the same order as their declaration in **router**.
823
824??? example "With a [middleware](../../middlewares/tcp/overview.md) -- using the [File Provider](../../providers/file.md)"
825
826    ```toml tab="TOML"
827    ## Dynamic configuration
828    [tcp.routers]
829      [tcp.routers.my-router]
830        rule = "HostSNI(`*`)"
831        # declared elsewhere
832        middlewares = ["ipwhitelist"]
833        service = "service-foo"
834    ```
835
836    ```yaml tab="YAML"
837    ## Dynamic configuration
838    tcp:
839      routers:
840        my-router:
841          rule: "HostSNI(`*`)"
842          # declared elsewhere
843          middlewares:
844          - ipwhitelist
845          service: service-foo
846    ```
847
848### Services
849
850You must attach a TCP [service](../services/index.md) per TCP router.
851Services are the target for the router.
852
853!!! important "TCP routers can only target TCP services (not HTTP services)."
854
855### TLS
856
857#### General
858
859When a TLS section is specified,
860it instructs Traefik that the current router is dedicated to TLS requests only (and that the router should ignore non-TLS requests).
861
862By default, a router with a TLS section will terminate the TLS connections, meaning that it will send decrypted data to the services.
863
864??? example "Router for TLS requests"
865
866    ```yaml tab="File (YAML)"
867    ## Dynamic configuration
868    tcp:
869      routers:
870        Router-1:
871          rule: "HostSNI(`foo-domain`)"
872          service: service-id
873          # will terminate the TLS request by default
874          tls: {}
875    ```
876
877    ```toml tab="File (TOML)"
878    ## Dynamic configuration
879    [tcp.routers]
880      [tcp.routers.Router-1]
881        rule = "HostSNI(`foo-domain`)"
882        service = "service-id"
883        # will terminate the TLS request by default
884        [tcp.routers.Router-1.tls]
885    ```
886
887#### `passthrough`
888
889As seen above, a TLS router will terminate the TLS connection by default.
890However, the `passthrough` option can be specified to set whether the requests should be forwarded "as is", keeping all data encrypted.
891
892It defaults to `false`.
893
894??? example "Configuring passthrough"
895
896    ```yaml tab="File (YAML)"
897    ## Dynamic configuration
898    tcp:
899      routers:
900        Router-1:
901          rule: "HostSNI(`foo-domain`)"
902          service: service-id
903          tls:
904            passthrough: true
905    ```
906
907    ```toml tab="File (TOML)"
908    ## Dynamic configuration
909    [tcp.routers]
910      [tcp.routers.Router-1]
911        rule = "HostSNI(`foo-domain`)"
912        service = "service-id"
913        [tcp.routers.Router-1.tls]
914          passthrough = true
915    ```
916
917#### `options`
918
919The `options` field enables fine-grained control of the TLS parameters.
920It refers to a [TLS Options](../../https/tls.md#tls-options) and will be applied only if a `HostSNI` rule is defined.
921
922!!! example "Configuring the tls options"
923
924    ```yaml tab="File (YAML)"
925    ## Dynamic configuration
926    tcp:
927      routers:
928        Router-1:
929          rule: "HostSNI(`foo-domain`)"
930          service: service-id
931          # will terminate the TLS request
932          tls:
933            options: foo
934
935    tls:
936      options:
937        foo:
938          minVersion: VersionTLS12
939          cipherSuites:
940            - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
941            - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
942            - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
943            - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
944            - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
945    ```
946
947    ```toml tab="File (TOML)"
948    ## Dynamic configuration
949    [tcp.routers]
950      [tcp.routers.Router-1]
951        rule = "HostSNI(`foo-domain`)"
952        service = "service-id"
953        # will terminate the TLS request
954        [tcp.routers.Router-1.tls]
955          options = "foo"
956
957    [tls.options]
958      [tls.options.foo]
959        minVersion = "VersionTLS12"
960        cipherSuites = [
961          "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
962          "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
963          "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
964          "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
965          "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
966        ]
967    ```
968
969#### `certResolver`
970
971See [`certResolver` for HTTP router](./index.md#certresolver) for more information.
972
973```yaml tab="File (YAML)"
974## Dynamic configuration
975tcp:
976  routers:
977    routerfoo:
978      rule: "HostSNI(`snitest.com`)"
979      tls:
980        certResolver: foo
981```
982
983```toml tab="File (TOML)"
984## Dynamic configuration
985[tcp.routers]
986  [tcp.routers.routerfoo]
987    rule = "HostSNI(`snitest.com`)"
988    [tcp.routers.routerfoo.tls]
989      certResolver = "foo"
990```
991
992#### `domains`
993
994See [`domains` for HTTP router](./index.md#domains) for more information.
995
996```yaml tab="File (YAML)"
997## Dynamic configuration
998tcp:
999  routers:
1000    routerbar:
1001      rule: "HostSNI(`snitest.com`)"
1002      tls:
1003        certResolver: "bar"
1004        domains:
1005          - main: "snitest.com"
1006            sans:
1007              - "*.snitest.com"
1008```
1009
1010```toml tab="File (TOML)"
1011## Dynamic configuration
1012[tcp.routers]
1013  [tcp.routers.routerbar]
1014    rule = "HostSNI(`snitest.com`)"
1015    [tcp.routers.routerbar.tls]
1016      certResolver = "bar"
1017      [[tcp.routers.routerbar.tls.domains]]
1018        main = "snitest.com"
1019        sans = ["*.snitest.com"]
1020```
1021
1022## Configuring UDP Routers
1023
1024!!! warning "The character `@` is not allowed in the router name"
1025
1026### General
1027
1028Similarly to TCP, as UDP is the transport layer, there is no concept of a request,
1029so there is no notion of an URL path prefix to match an incoming UDP packet with.
1030Furthermore, as there is no good TLS support at the moment for multiple hosts,
1031there is no Host SNI notion to match against either.
1032Therefore, there is no criterion that could be used as a rule to match incoming packets in order to route them.
1033So UDP "routers" at this time are pretty much only load-balancers in one form or another.
1034
1035!!! important "Sessions and timeout"
1036
1037	Even though UDP is connectionless (and because of that),
1038	the implementation of an UDP router in Traefik relies on what we (and a couple of other implementations) call a `session`.
1039	It basically means that some state is kept about an ongoing communication between a client and a backend,
1040	notably so that the proxy knows where to forward a response packet from a backend.
1041	As expected, a `timeout` is associated to each of these sessions,
1042	so that they get cleaned out if they go through a period of inactivity longer than a given duration.
1043	Timeout can be configured using the `entryPoints.name.udp.timeout` option as described
1044	under [entry points](../entrypoints/#udp-options).
1045
1046### EntryPoints
1047
1048If not specified, UDP routers will accept packets from all defined (UDP) entry points.
1049If one wants to limit the router scope to a set of entry points, one should set the entry points option.
1050
1051??? example "Listens to Every Entry Point"
1052
1053    **Dynamic Configuration**
1054
1055    ```yaml tab="File (YAML)"
1056    ## Dynamic configuration
1057
1058    udp:
1059      routers:
1060        Router-1:
1061          # By default, routers listen to all UDP entrypoints
1062          # i.e. "other", and "streaming".
1063          service: "service-1"
1064    ```
1065
1066    ```toml tab="File (TOML)"
1067    ## Dynamic configuration
1068
1069    [udp.routers]
1070      [udp.routers.Router-1]
1071        # By default, routers listen to all UDP entrypoints,
1072        # i.e. "other", and "streaming".
1073        service = "service-1"
1074    ```
1075
1076    **Static Configuration**
1077
1078    ```yaml tab="File (YAML)"
1079    ## Static configuration
1080
1081    entryPoints:
1082      # not used by UDP routers
1083      web:
1084        address: ":80"
1085      # used by UDP routers
1086      other:
1087        address: ":9090/udp"
1088      streaming:
1089        address: ":9191/udp"
1090    ```
1091
1092    ```toml tab="File (TOML)"
1093    ## Static configuration
1094
1095    [entryPoints]
1096      # not used by UDP routers
1097      [entryPoints.web]
1098        address = ":80"
1099      # used by UDP routers
1100      [entryPoints.other]
1101        address = ":9090/udp"
1102      [entryPoints.streaming]
1103        address = ":9191/udp"
1104    ```
1105
1106    ```bash tab="CLI"
1107    ## Static configuration
1108    --entrypoints.web.address=":80"
1109    --entrypoints.other.address=":9090/udp"
1110    --entrypoints.streaming.address=":9191/udp"
1111    ```
1112
1113??? example "Listens to Specific Entry Points"
1114
1115    **Dynamic Configuration**
1116
1117    ```yaml tab="File (YAML)"
1118    ## Dynamic configuration
1119    udp:
1120      routers:
1121        Router-1:
1122          # does not listen on "other" entry point
1123          entryPoints:
1124            - "streaming"
1125          service: "service-1"
1126    ```
1127
1128    ```toml tab="File (TOML)"
1129    ## Dynamic configuration
1130    [udp.routers]
1131      [udp.routers.Router-1]
1132        # does not listen on "other" entry point
1133        entryPoints = ["streaming"]
1134        service = "service-1"
1135    ```
1136
1137    **Static Configuration**
1138
1139    ```yaml tab="File (YAML)"
1140    ## Static configuration
1141
1142    entryPoints:
1143      web:
1144        address: ":80"
1145      other:
1146        address: ":9090/udp"
1147      streaming:
1148        address: ":9191/udp"
1149    ```
1150
1151    ```toml tab="File (TOML)"
1152    ## Static configuration
1153
1154    [entryPoints]
1155      [entryPoints.web]
1156        address = ":80"
1157      [entryPoints.other]
1158        address = ":9090/udp"
1159      [entryPoints.streaming]
1160        address = ":9191/udp"
1161    ```
1162
1163    ```bash tab="CLI"
1164    ## Static configuration
1165    --entrypoints.web.address=":80"
1166    --entrypoints.other.address=":9090/udp"
1167    --entrypoints.streaming.address=":9191/udp"
1168    ```
1169
1170### Services
1171
1172There must be one (and only one) UDP [service](../services/index.md) referenced per UDP router.
1173Services are the target for the router.
1174
1175!!! important "UDP routers can only target UDP services (and not HTTP or TCP services)."
1176