Skip to content

fix(networking): Add absolute FQDNs (trailing dot) to VirtualHost domains#56008

Merged
istio-testing merged 5 commits intoistio:masterfrom
ankushagarwal:fqdn-56007
Apr 21, 2025
Merged

fix(networking): Add absolute FQDNs (trailing dot) to VirtualHost domains#56008
istio-testing merged 5 commits intoistio:masterfrom
ankushagarwal:fqdn-56007

Conversation

@ankushagarwal
Copy link
Copy Markdown
Contributor

@ankushagarwal ankushagarwal commented Apr 18, 2025

Description:

This PR fixes an issue where Istio's outbound route configuration (RouteConfiguration) did not include the absolute/fully qualified domain name (FQDN) variant (e.g., my-service.my-ns.svc.cluster.local.) in the domains list for VirtualHost entries.

Updated the TestGenerateVirtualHostDomains test to verify new functionality

Problem:

When clients make requests using the absolute FQDN (with the trailing dot) in the Host header, Envoy would fail to match this against the specific VirtualHost domains generated by Istio. This caused such requests to fall back to the wildcard (*) virtual host, typically resulting in routing to the PassthroughCluster or BlackHoleCluster instead of the intended service cluster and associated Istio policies (like VirtualServices, DestinationRules).

Example scenario from issue report:

  • curl http://foo.bar.svc.cluster.local/ -> Correctly matches outbound|80||foo.bar.svc.cluster.local
  • curl http://foo.bar.svc.cluster.local./ -> Incorrectly matches PassthroughCluster

Solution:

The generateVirtualHostDomains function in pilot/pkg/networking/core/route.go has been modified to explicitly add the absolute FQDN variant (hostname + ".") to the list of generated domains for each service hostname and alias, provided the name is not an IP address.

Fixes #56007

…ains

**Description:**

This PR fixes an issue where Istio's outbound route configuration (`RouteConfiguration`) did not include the absolute/fully qualified domain name (FQDN) variant (e.g., `my-service.my-ns.svc.cluster.local.`) in the `domains` list for `VirtualHost` entries.

Updated the TestGenerateVirtualHostDomains test to verify new functionality

**Problem:**

When clients make requests using the absolute FQDN (with the trailing dot) in the `Host` header, Envoy would fail to match this against the specific `VirtualHost` domains generated by Istio. This caused such requests to fall back to the wildcard (`*`) virtual host, typically resulting in routing to the `PassthroughCluster` or `BlackHoleCluster` instead of the intended service cluster and associated Istio policies (like VirtualServices, DestinationRules).

Example scenario from issue report:
- `curl http://foo.bar.svc.cluster.local/` -> Correctly matches `outbound|80||foo.bar.svc.cluster.local`
- `curl http://foo.bar.svc.cluster.local./` -> Incorrectly matches `PassthroughCluster`

**Solution:**

The `generateVirtualHostDomains` function in `pilot/pkg/networking/core/route.go` has been modified to explicitly add the absolute FQDN variant (`hostname + "."`) to the list of generated domains for each service hostname and alias, provided the name is not an IP address.
@ankushagarwal ankushagarwal requested a review from a team as a code owner April 18, 2025 16:37
@istio-policy-bot istio-policy-bot added area/networking release-notes-none Indicates a PR that does not require release notes. labels Apr 18, 2025
@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla bot commented Apr 18, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@istio-policy-bot
Copy link
Copy Markdown

😊 Welcome @ankushagarwal! This is either your first contribution to the Istio istio repo, or it's been
a while since you've been here.

You can learn more about the Istio working groups, Code of Conduct, and contribution guidelines
by referring to Contributing to Istio.

Thanks for contributing!

Courtesy of your friendly welcome wagon.

@istio-testing istio-testing added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. needs-ok-to-test labels Apr 18, 2025
@istio-testing
Copy link
Copy Markdown
Collaborator

Hi @ankushagarwal. Thanks for your PR.

I'm waiting for a istio member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@keithmattix
Copy link
Copy Markdown
Contributor

/ok-to-test

@istio-testing istio-testing added ok-to-test Set this label allow normal testing to take place for a PR not submitted by an Istio org member. and removed needs-ok-to-test labels Apr 18, 2025
@keithmattix
Copy link
Copy Markdown
Contributor

Looks like this is certainly legal according to the RFC: https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2. I'm curious why we haven't allowed this in the past; I'll let @ramaraochavali @hzxuzhonghu or @howardjohn explain this fence for me :)

Copy link
Copy Markdown
Member

@howardjohn howardjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me. I cannot think of what this would break but I suppose its possible there is some edge case not considered... may be best put an on-by-default feature flag around this just in case?

cc @ramaraochavali

for _, s := range all {
// Check if 's' is an IP address. We don't add trailing dots to IPs.
isIP := net.ParseIP(s) != nil
// Add the absolute FQDN variant (with trailing dot) if it's not an IP address.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: does this make sense under GenerateAltVirtualHosts since its basically an alt host?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to move there

@ramaraochavali
Copy link
Copy Markdown
Contributor

LGTM. Add feature flag with default true

@ankushagarwal ankushagarwal requested a review from a team as a code owner April 19, 2025 14:50
@ankushagarwal
Copy link
Copy Markdown
Contributor Author

Thank you for the feedback @ramaraochavali and @howardjohn - moved to GenerateAltVirtualHosts and added a default true feature flag - PILOT_ENABLE_ABSOLUTE_FQDN_VHOST_DOMAIN

@istio-testing istio-testing added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Apr 19, 2025
Copy link
Copy Markdown
Contributor

@sridhargaddam sridhargaddam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a release note.

Comment on lines +280 to +281
"If set to true, Istio will add the absolute FQDN variant (e.g., my-service.my-ns.svc.cluster.local.) "+
"to the domains list for VirtualHost entries. Defaults to true, enabling the addition.",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the default value is true, lets modify the description to...

Suggested change
"If set to true, Istio will add the absolute FQDN variant (e.g., my-service.my-ns.svc.cluster.local.) "+
"to the domains list for VirtualHost entries. Defaults to true, enabling the addition.",
"If set to false, Istio will not add the absolute FQDN variant (e.g., my-service.my-ns.svc.cluster.local.) to the domains list for VirtualHost entries.",

@istio-testing
Copy link
Copy Markdown
Collaborator

istio-testing commented Apr 20, 2025

@ankushagarwal: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
integ-ambient-mc_istio 7eabec6 link false /test integ-ambient-mc
Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@ankushagarwal
Copy link
Copy Markdown
Contributor Author

Added release notes, fixed lint, updated the description of the flag

Copy link
Copy Markdown
Contributor

@sridhargaddam sridhargaddam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @ankushagarwal

@istio-testing istio-testing merged commit ce55506 into istio:master Apr 21, 2025
29 of 30 checks passed
tjons pushed a commit to tjons/istio that referenced this pull request Apr 26, 2025
…ains (istio#56008)

* fix(networking): Add absolute FQDNs (trailing dot) to VirtualHost domains

**Description:**

This PR fixes an issue where Istio's outbound route configuration (`RouteConfiguration`) did not include the absolute/fully qualified domain name (FQDN) variant (e.g., `my-service.my-ns.svc.cluster.local.`) in the `domains` list for `VirtualHost` entries.

Updated the TestGenerateVirtualHostDomains test to verify new functionality

**Problem:**

When clients make requests using the absolute FQDN (with the trailing dot) in the `Host` header, Envoy would fail to match this against the specific `VirtualHost` domains generated by Istio. This caused such requests to fall back to the wildcard (`*`) virtual host, typically resulting in routing to the `PassthroughCluster` or `BlackHoleCluster` instead of the intended service cluster and associated Istio policies (like VirtualServices, DestinationRules).

Example scenario from issue report:
- `curl http://foo.bar.svc.cluster.local/` -> Correctly matches `outbound|80||foo.bar.svc.cluster.local`
- `curl http://foo.bar.svc.cluster.local./` -> Incorrectly matches `PassthroughCluster`

**Solution:**

The `generateVirtualHostDomains` function in `pilot/pkg/networking/core/route.go` has been modified to explicitly add the absolute FQDN variant (`hostname + "."`) to the list of generated domains for each service hostname and alias, provided the name is not an IP address.

* Move the fqdn dot suffix logic to GenerateAltVirtualHosts, reorder test expected results

* Add PILOT_ENABLE_ABSOLUTE_FQDN_VHOST_DOMAIN feature flag

* Update tests

* [release-notes] Add release note, fix lint
fjglira pushed a commit to fjglira/istio that referenced this pull request Sep 26, 2025
* upstream/master:
  remove 1.23 compatibility profile (istio#56023)
  Create ambient multinetwork flag (istio#55991)
  krt: make krt and kube client indexes named (istio#55999)
  Automator: update proxy@master in istio/istio@master (istio#56026)
  fix istio-revision-tag-default MutatingWebhookConfigurations is not created during installation (istio#56004)
  doc: fix typo in accesslog test (istio#55117)
  fix(networking): Add absolute FQDNs (trailing dot) to VirtualHost domains (istio#56008)
kannanjgithub pushed a commit to grpc/grpc-java that referenced this pull request Feb 9, 2026
…12644)

## Summary

`matchHostName` in `RoutingUtils` and `XdsNameResolver` currently
rejects hostnames and patterns
with a trailing dot (`.`) via `checkArgument`. A trailing dot denotes a
**Fully Qualified Domain Name (FQDN)** as defined in
[RFC 1034 Section
3.1](https://www.rfc-editor.org/rfc/rfc1034#section-3.1), and is a
valid,
well-defined representation of an absolute domain name. Rejecting it is
inconsistent with the RFC.

This change removes the trailing-dot rejection and adds normalization to
strip the trailing dot
before matching, making `example.com.` and `example.com` match
equivalently.

## Background

Per [RFC 1034 Section
3.1](https://www.rfc-editor.org/rfc/rfc1034#section-3.1):

> "If the name ends with a dot, it is an absolute name ... For example,
`poneria.ISI.EDU.`"

A trailing dot simply indicates that the name is rooted at the DNS root
and is semantically
equivalent to the same name without the trailing dot. Treating it as
invalid prevents legitimate
FQDNs from being used as hostnames or virtual host domain patterns in
xDS routing configuration.

## Motivation

This was discovered when using gRPC Proxyless Service Mesh on a
Kubernetes cluster with Istio.
The issue surfaced after upgrading Istio from 1.26.8 to 1.28.3. The
Istio change
[istio/istio#56008](istio/istio#56008) began
sending FQDN-style domain
names (with trailing dots) in xDS route configuration, which caused
grpc-java to throw an
`IllegalArgumentException` in `matchHostName`:

```text
java.lang.IllegalArgumentException: Invalid pattern/domain name
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:143)
```

The root cause is that grpc-java's `matchHostName` was not RFC-compliant
in rejecting trailing dots — the Istio upgrade merely made it visible.
The fix here is to bring grpc-java into compliance with RFC 1034,
independent of any specific Istio version.

## Changes

- `xds/src/main/java/io/grpc/xds/RoutingUtils.java`: Removed
trailing-dot rejection and added
  FQDN normalization in `matchHostName`.
- `xds/src/main/java/io/grpc/xds/XdsNameResolver.java`: Same as above.
- `xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java`: Added
`matchHostName_trailingDot`
test covering exact match, prefix wildcard, and suffix wildcard with
trailing dot combinations.

## References

- [RFC 1034 – Domain Names: Concepts and
Facilities](https://www.rfc-editor.org/rfc/rfc1034)
- [RFC 1035 – Domain Names: Implementation and
Specification](https://www.rfc-editor.org/rfc/rfc1035)
- [istio/istio#56008](istio/istio#56008) – Istio
change that began sending FQDN domain names in xDS configuration
jdcormie pushed a commit to jdcormie/grpc-java that referenced this pull request Feb 11, 2026
…rpc#12644)

## Summary

`matchHostName` in `RoutingUtils` and `XdsNameResolver` currently
rejects hostnames and patterns
with a trailing dot (`.`) via `checkArgument`. A trailing dot denotes a
**Fully Qualified Domain Name (FQDN)** as defined in
[RFC 1034 Section
3.1](https://www.rfc-editor.org/rfc/rfc1034#section-3.1), and is a
valid,
well-defined representation of an absolute domain name. Rejecting it is
inconsistent with the RFC.

This change removes the trailing-dot rejection and adds normalization to
strip the trailing dot
before matching, making `example.com.` and `example.com` match
equivalently.

## Background

Per [RFC 1034 Section
3.1](https://www.rfc-editor.org/rfc/rfc1034#section-3.1):

> "If the name ends with a dot, it is an absolute name ... For example,
`poneria.ISI.EDU.`"

A trailing dot simply indicates that the name is rooted at the DNS root
and is semantically
equivalent to the same name without the trailing dot. Treating it as
invalid prevents legitimate
FQDNs from being used as hostnames or virtual host domain patterns in
xDS routing configuration.

## Motivation

This was discovered when using gRPC Proxyless Service Mesh on a
Kubernetes cluster with Istio.
The issue surfaced after upgrading Istio from 1.26.8 to 1.28.3. The
Istio change
[istio/istio#56008](istio/istio#56008) began
sending FQDN-style domain
names (with trailing dots) in xDS route configuration, which caused
grpc-java to throw an
`IllegalArgumentException` in `matchHostName`:

```text
java.lang.IllegalArgumentException: Invalid pattern/domain name
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:143)
```

The root cause is that grpc-java's `matchHostName` was not RFC-compliant
in rejecting trailing dots — the Istio upgrade merely made it visible.
The fix here is to bring grpc-java into compliance with RFC 1034,
independent of any specific Istio version.

## Changes

- `xds/src/main/java/io/grpc/xds/RoutingUtils.java`: Removed
trailing-dot rejection and added
  FQDN normalization in `matchHostName`.
- `xds/src/main/java/io/grpc/xds/XdsNameResolver.java`: Same as above.
- `xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java`: Added
`matchHostName_trailingDot`
test covering exact match, prefix wildcard, and suffix wildcard with
trailing dot combinations.

## References

- [RFC 1034 – Domain Names: Concepts and
Facilities](https://www.rfc-editor.org/rfc/rfc1034)
- [RFC 1035 – Domain Names: Implementation and
Specification](https://www.rfc-editor.org/rfc/rfc1035)
- [istio/istio#56008](istio/istio#56008) – Istio
change that began sending FQDN domain names in xDS configuration
AgraVator pushed a commit to AgraVator/grpc-java that referenced this pull request Feb 25, 2026
…rpc#12644)

## Summary

`matchHostName` in `RoutingUtils` and `XdsNameResolver` currently
rejects hostnames and patterns
with a trailing dot (`.`) via `checkArgument`. A trailing dot denotes a
**Fully Qualified Domain Name (FQDN)** as defined in
[RFC 1034 Section
3.1](https://www.rfc-editor.org/rfc/rfc1034#section-3.1), and is a
valid,
well-defined representation of an absolute domain name. Rejecting it is
inconsistent with the RFC.

This change removes the trailing-dot rejection and adds normalization to
strip the trailing dot
before matching, making `example.com.` and `example.com` match
equivalently.

## Background

Per [RFC 1034 Section
3.1](https://www.rfc-editor.org/rfc/rfc1034#section-3.1):

> "If the name ends with a dot, it is an absolute name ... For example,
`poneria.ISI.EDU.`"

A trailing dot simply indicates that the name is rooted at the DNS root
and is semantically
equivalent to the same name without the trailing dot. Treating it as
invalid prevents legitimate
FQDNs from being used as hostnames or virtual host domain patterns in
xDS routing configuration.

## Motivation

This was discovered when using gRPC Proxyless Service Mesh on a
Kubernetes cluster with Istio.
The issue surfaced after upgrading Istio from 1.26.8 to 1.28.3. The
Istio change
[istio/istio#56008](istio/istio#56008) began
sending FQDN-style domain
names (with trailing dots) in xDS route configuration, which caused
grpc-java to throw an
`IllegalArgumentException` in `matchHostName`:

```text
java.lang.IllegalArgumentException: Invalid pattern/domain name
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:143)
```

The root cause is that grpc-java's `matchHostName` was not RFC-compliant
in rejecting trailing dots — the Istio upgrade merely made it visible.
The fix here is to bring grpc-java into compliance with RFC 1034,
independent of any specific Istio version.

## Changes

- `xds/src/main/java/io/grpc/xds/RoutingUtils.java`: Removed
trailing-dot rejection and added
  FQDN normalization in `matchHostName`.
- `xds/src/main/java/io/grpc/xds/XdsNameResolver.java`: Same as above.
- `xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java`: Added
`matchHostName_trailingDot`
test covering exact match, prefix wildcard, and suffix wildcard with
trailing dot combinations.

## References

- [RFC 1034 – Domain Names: Concepts and
Facilities](https://www.rfc-editor.org/rfc/rfc1034)
- [RFC 1035 – Domain Names: Implementation and
Specification](https://www.rfc-editor.org/rfc/rfc1035)
- [istio/istio#56008](istio/istio#56008) – Istio
change that began sending FQDN domain names in xDS configuration
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/networking ok-to-test Set this label allow normal testing to take place for a PR not submitted by an Istio org member. release-notes-none Indicates a PR that does not require release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Istio does not generate routing config for absolute / fqdn (dot at the end of the name) example: foo.bar.svc.cluster.local.

7 participants