Skip to content

conn_manager: allow to remove port from host header#10960

Merged
mattklein123 merged 18 commits intoenvoyproxy:masterfrom
tehnerd:http_patch
May 8, 2020
Merged

conn_manager: allow to remove port from host header#10960
mattklein123 merged 18 commits intoenvoyproxy:masterfrom
tehnerd:http_patch

Conversation

@tehnerd
Copy link
Contributor

@tehnerd tehnerd commented Apr 27, 2020

Commit Message:

add an api option/conn manager feature which would allow to remove port part from Host header (e.g. would transform
example:443 to example. this would simplify domain's matching inside virtual host as well as would not require explicit matching on "domain:port" in upstream proxies.

Additional Description:
in production we see a lot of external requests from third party libraries, which are setting port part even for requests toward common port (443). w/o this diff on envoy side workaround was to match both on "example.com" and "example.com:443" in domains configuration. and to do this on every layer of proxies. as well as modifying application, which was running behind last level envoy, to do the same.

this diff would allow to set up remove_port option on first level envoy, and everywhere just to match on "example.com"

as a side effect it should also help to resolve #886

Risk Level:
LOW
Testing:
new unit tests + manual testing
Docs Changes:
inline in proto file

@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/.

🐱

Caused by: #10960 was opened by tehnerd.

see: more, trace.

@tehnerd
Copy link
Contributor Author

tehnerd commented Apr 27, 2020

i will fix failed builds/ signoff the diff. for now just waiting for everything else to complete (to make sure that there is nothing else to fix)

@euroelessar
Copy link
Contributor

Please add test cases for authority headers with IPv4/IPv6 addresses

Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

Thanks. While we wait for review from the API maintainers, I provided a couple of quick comments.

Copy link
Member

Choose a reason for hiding this comment

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

I think the name of this field should be more specific. Something like strip_host_port. Another thing to consider is how this interacts with auto host rewrite and other host-manipulation features.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks. yeah. naming is hard. i will wait for other comments and will address yours in next iteration.

as for auto host - from my understanding auto host is a part of Route component of the envoy. and this port stripping modifies host header before we hit it (see "RouteShouldUseNormalizedHost" unittest)

Copy link
Member

Choose a reason for hiding this comment

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

I will be honest that my initial gut on this one is to not strip the port, but to instead add a routing option that would ignore port during route matching. I think the latter would be the most natural way of solving #886. However, I see your point about doing stripping once and then not having to worry about upstream proxies.

I would definitely like to hear from @alyssawilk and @PiotrSikora on this one.

Copy link
Member

Choose a reason for hiding this comment

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

Also prefer moving to a routing option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as Matt mentioned, matching in routing option would solve #866 (which was bonus point in this diff). but wont allow to simplify configuration for multiple layers of proxies and backends behind them (even if envoy on 2nd layer would ignore port matching, backend behind it wont; that would increas complexity of migrating from other proxies (nginx as example) to envoy).

Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we already removed the port when it matched the scheme, i.e. an http://foo.com:80 and https://foo.com:443 but apparently I'm misremembering? Anyway I'd prefer this as a routing option. I'm OK with a configuration guarded removal iff the port matches the listening port - if they don't match removing it feels sketchy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

on matched the scheme. (unless it was change in last few days):

curl -k -v https://localhost/ -H 'Host:localhost'

* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 7
< content-type: text/plain
< date: Tue, 28 Apr 2020 19:22:16 GMT
< server: envoy
< 

 curl -k -v https://localhost/ -H 'Host:localhost:443'

* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< date: Tue, 28 Apr 2020 19:23:06 GMT
< server: envoy
< content-length: 0
< 

part of envoy's test configuration which we are hitting in this example:

 - name: local_service
              domains: ["localhost"]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as for the matching port - i'm not that familiar with this codepath. is it even possible to get listener object (and therefor it's port) from connection manager and/or route object?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, so seems it is possible to get NetworkConnection from ActiveStream, and therefor local port. now the question is - do you want to make it part of the route object? (and therefor force users to match on "xxx:443" in domains (in this case this diff make little sense, and new one should be made), or you are ok w/ it being part of conn manager (but with removing port only if it is equal to the listeners port)?

Copy link
Member

Choose a reason for hiding this comment

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

In a perfect world I think we should have both options, route matching with port stripping, as well as this option to strip port IFF the port matches the bound port (per @alyssawilk), but it's fine if you only want to do the latter in this PR.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think this belongs in PathUtil. There's at least one other authority-related method in header_utility.h/cc's HeaderUtility class.

Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

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

This is looking great, especially the thorough unit testing in RemovePortsFromHost :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

mind changing Host -> host here and below?
I know Host is pretty standard for HTTP/1.1 but Envoy lowercases anyway and I think it's more consistent with other API docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure.

Copy link
Contributor

Choose a reason for hiding this comment

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

For sure looking at connection it must be a valid pointer as it's returning a pointer to a reference member.
I think it'd be fine to change both of these to asserts - I think if we create an HTTPConnectionManager with non-valid address we've violated earlier invariants.

Copy link
Contributor

Choose a reason for hiding this comment

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

Super nitty, but
->
Return local port of the connection.

If you could check the comments below too that'd be awesome.

Copy link
Contributor

Choose a reason for hiding this comment

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

At the point we call this, we've either added a default host for HTTP/1.0 or sent a local reply and will not reach this point (HCM 850)
I don't mind you making it resilient to changes in code order, but if you're going to leave this in please make sure it's unit tested.

Copy link
Contributor

Choose a reason for hiding this comment

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

optional, maybe something about the matching in the naming? strip_matching_host_port?

Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

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

Looking great - just a few more comment nits and you're good to go!

Copy link
Contributor

Choose a reason for hiding this comment

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

I think there's still some Host -> host changes to track down :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

Port -> The port
and I'd change "connect" to CONNECT again just for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

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

really small nit but port -> the port ?

@repokitteh-read-only
Copy link

CC @envoyproxy/api-watchers: FYI only for changes made to api/.

🐱

Caused by: #10960 was synchronize by tehnerd.

see: more, trace.

alyssawilk
alyssawilk previously approved these changes May 5, 2020
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

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

@mattklein123 up for API sign off?

@mattklein123 mattklein123 self-assigned this May 5, 2020
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Nice! Few small comments from a quick skim. Thank you!

/wait

Copy link
Member

Choose a reason for hiding this comment

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

This needs a release note. Also, do you mind ref linking fields in here where you can? For example domains.

Copy link
Member

Choose a reason for hiding this comment

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

nit: generally we don't do asserts like this since it will crash in an obvious way on the next line. I would just remove the conn variable.

tehnerd added 10 commits May 6, 2020 19:55
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
1. renaming remove_port to strip_host_port
2. stripping port only when it is equal to listener's local port

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
changes:
1. renaming strip_host_port to strip_matching_...
2. renaming shouldRemovePort to shouldRemoveMatchingPort
3. do not remove port if method is "connect"
4. removing some unnecessary checks

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
addressing nits/comments on spelling

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
* removed ASSERT from localPort helper
* added ref into prot description
* added ref to release notes
* rebase

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
tehnerd added 3 commits May 7, 2020 16:32
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
…p_patch

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Awesome thank you. Just a small doc nit and let's ship!

/wait

Can be reverted temporarily by setting runtime feature `envoy.reloadable_features.fix_upgrade_response` to false.
* http: remove legacy connection pool code and their runtime features: `envoy.reloadable_features.new_http1_connection_pool_behavior` and
`envoy.reloadable_features.new_http2_connection_pool_behavior`.
* http connection manager: added :ref:`stripping port from host header <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.strip_matching_host_port>` support.
Copy link
Member

Choose a reason for hiding this comment

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

s/http connection manager/http

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
@tehnerd
Copy link
Contributor Author

tehnerd commented May 7, 2020

forget to format. will do another commit

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
mattklein123
mattklein123 previously approved these changes May 7, 2020
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks!

@repokitteh-read-only repokitteh-read-only bot removed the api label May 7, 2020
@mattklein123
Copy link
Member

/azp run envoy-presubmit

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@mattklein123
Copy link
Member

/azp run envoy-presubmit

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@mattklein123
Copy link
Member

Sorry looks like you lost the merge race. :( Can you merge master again?

/wait

tehnerd added 2 commits May 8, 2020 03:55
…p_patch

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Better handling for domain matching with ports

6 participants