Repository: traefik/traefik (language: go)

Issue:
The log reports an error, but the function is normal.
### Welcome!

- [X] Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
- [X] Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any.

### What did you do?

I configure dynamic file during runtime.
Dynamic file is below:
```yaml
http:

  routers:
    dashboard-http:
      rule: "Host(`xxxx:xxxx::xx``)"  # xxxx:xxxx::xx is an IPv6 address
      service: service
      entryPoints:
        - web
      middlewares:
        - redirect-https
      priority: 1

    dashboard-https:
      entryPoints:
        - websecure
      rule: "Host(`xxxx:xxxx::xx`)" # xxxx:xxxx::xx is an IPv6 address
      service: service
      priority: 1
      tls: {}

  services:
    service:
      loadBalancer:
        servers:
          - url: "https://xxx.xx.xxx.xx:xxxxx" # xxx.xx.xxx.xx:xxxxx is an IPv4 address + port
```

The log will report an error：time="2023-02-02T16:45:18+08:00" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"xxxx:xxxx::xx\" is not a valid hostname".However, the agent function can work normally.

This error should not occur under normal circumstances.

### What did you see instead?

The log will report an error：time="2023-02-02T16:45:18+08:00" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"xxxx:xxxx::xx\" is not a valid hostname".

### What version of Traefik are you using?

v2.9.6 （I tested it on a physical machine）

### What is your environment & configuration?

```yaml
http:

  routers:
    dashboard-http:
      rule: "Host(`xxxx:xxxx::xx``)"  # xxxx:xxxx::xx is an IPv6 address
      service: service
      entryPoints:
        - web
      middlewares:
        - redirect-https
      priority: 1

    dashboard-https:
      entryPoints:
        - websecure
      rule: "Host(`xxxx:xxxx::xx`)" # xxxx:xxxx::xx is an IPv6 address
      service: service
      priority: 1
      tls: {}

  services:
    service:
      loadBalancer:
        servers:
          - url: "https://xxx.xx.xxx.xx:xxxxx" # xxx.xx.xxx.xx:xxxxx is an IPv4 address + port

# middlewares
http:
  middlewares:
    redirect-https:
      redirectScheme:
        scheme: https
        permanent: true
```

Add more configuration information here.

```yaml
api:
  debug: true
  dashboard: true
  insecure: true

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"


providers:
  file:
    directory: /etc/traefik/configurations/

log:
  filePath: /var/log/traefik/traefik.log

accessLog:
  filePath: /var/log/traefik/access.log
  bufferingSize: 100
  fields:
    names:
      StartLocal: keep
      StaartUTC: drop

serversTransport:
  insecureSkipVerify: true
```


### If applicable, please paste the log output in DEBUG level

```
time="2023-02-02T17:17:04+08:00" level=debug msg="Creating middleware" middlewareType=Recovery entryPointName=websecure middlewareName=traefik-internal-recovery
time="2023-02-02T17:17:04+08:00" level=debug msg="Adding route for xxxx:xxxx::xx with TLS options default" entryPointName=websecure
time="2023-02-02T17:17:04+08:00" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"xxxx:xxxx::xx\" is not a valid hostname"
time="2023-02-02T17:17:06+08:00" level=debug msg="Configuration received: {\"http\":{\"routers\":{\"dashboard-http\":{\"entryPoints\":[\"web\"],\"middlewares\":[\"redirect-https\"],\"service\":\"service\",\"rule\":\"Host(`xxxx:xxxx::xx`)\",\"priority\":1},\"dashboard-https\":{\"entryPoints\":[\"websecure\"],\"service\":\"service\",\"rule\":\"Host(`xxxx:xxxx::xx`)\",\"priority\":1,\"tls\":{}}},\"services\":{\"k8s-service\":{\"loadBalancer\":{\"servers\":[{\"url\":\"https://xxx.xx.xxx.xx:xxxxx\"}],\"passHostHeader\":true}}},\"middlewares\":{\"redirect-https\":{\"redirectScheme\":{\"scheme\":\"https\",\"permanent\":true}}}},\"tcp\":{},\"udp\":{},\"tls\":{}}" providerName=file
time="2023-02-02T17:17:06+08:00" level=debug msg="Skipping unchanged configuration." providerName=file
```


Discussion / hints:

Fix patch:
diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go
index e21dfc75de..093c182d03 100644
--- a/pkg/muxer/tcp/mux.go
+++ b/pkg/muxer/tcp/mux.go
@@ -315,7 +315,7 @@ func alpn(tree *matchersTree, protos ...string) error {
 	return nil
 }
 
-var almostFQDN = regexp.MustCompile(`^[[:alnum:]\.-]+$`)
+var hostOrIP = regexp.MustCompile(`^[[:alnum:]\.\-\:]+$`)
 
 // hostSNI checks if the SNI Host of the connection match the matcher host.
 func hostSNI(tree *matchersTree, hosts ...string) error {
@@ -329,8 +329,8 @@ func hostSNI(tree *matchersTree, hosts ...string) error {
 			continue
 		}
 
-		if !almostFQDN.MatchString(host) {
-			return fmt.Errorf("invalid value for \"HostSNI\" matcher, %q is not a valid hostname", host)
+		if !hostOrIP.MatchString(host) {
+			return fmt.Errorf("invalid value for \"HostSNI\" matcher, %q is not a valid hostname or IP", host)
 		}
 
 		hosts[i] = strings.ToLower(host)


Test patch:
diff --git a/pkg/muxer/http/mux_test.go b/pkg/muxer/http/mux_test.go
index be8e2de301..0f6649dc73 100644
--- a/pkg/muxer/http/mux_test.go
+++ b/pkg/muxer/http/mux_test.go
@@ -63,6 +63,20 @@ func Test_addRoute(t *testing.T) {
 				"http://localhost/foo": http.StatusOK,
 			},
 		},
+		{
+			desc: "Host IPv4",
+			rule: "Host(`127.0.0.1`)",
+			expected: map[string]int{
+				"http://127.0.0.1/foo": http.StatusOK,
+			},
+		},
+		{
+			desc: "Host IPv6",
+			rule: "Host(`10::10`)",
+			expected: map[string]int{
+				"http://10::10/foo": http.StatusOK,
+			},
+		},
 		{
 			desc:          "Non-ASCII Host",
 			rule:          "Host(`locàlhost`)",
diff --git a/pkg/muxer/tcp/mux_test.go b/pkg/muxer/tcp/mux_test.go
index 50b8938cf7..f33398ef5a 100644
--- a/pkg/muxer/tcp/mux_test.go
+++ b/pkg/muxer/tcp/mux_test.go
@@ -740,7 +740,7 @@ func Test_HostSNI(t *testing.T) {
 		},
 		{
 			desc:       "Matching hosts",
-			ruleHosts:  []string{"foobar"},
+			ruleHosts:  []string{"foobar", "foo-bar.baz"},
 			serverName: "foobar",
 		},
 		{
@@ -748,6 +748,16 @@ func Test_HostSNI(t *testing.T) {
 			ruleHosts:  []string{"foo.bar"},
 			serverName: "foo.bar",
 		},
+		{
+			desc:       "Matching IPv4",
+			ruleHosts:  []string{"127.0.0.1"},
+			serverName: "127.0.0.1",
+		},
+		{
+			desc:       "Matching IPv6",
+			ruleHosts:  []string{"10::10"},
+			serverName: "10::10",
+		},
 	}
 
 	for _, test := range testCases {