Qpid Proton
  1. Qpid Proton
  2. PROTON-160

Allow open.hostname to be configured independently of network hostname

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 0.1, 0.2
    • Fix Version/s: 0.5
    • Component/s: proton-c, proton-j
    • Labels:

      Description

      In a scaled-out, multi-tenant broker environment, the host on which the container is running is often different from the host to which a client is establishing the tcp connection. The 'hostname' field in the connection open performative was added to support this scenario. Currently there's no way to control this from the Messenger API.

      Options include:

      (1) (preferred) add a new 'networkhost' field to Message to allow the network address to be specified. If provided, this information would be used when establishing the network connection and the data in the 'address' field would be used in the connection open hostname field. This is somewhat in line with the way that connection redirect (amqp:connection:redirect) is specified.

      (2) extend the syntax of address with query string to supply hostname, e.g., username:password@tcpaddress:tcpport/entityname?hostname=foo where 'foo' would become the hostname used in the connection open frame. This is the approach used by the current Qpid AMQP 1.0 JMS client.

        Activity

        Hide
        Rafael H. Schloming added a comment -

        This has sat for a while now, and there are various more specific JIRAs for other SSL issues, so I'm going to consider this fixed by the new route APIs until I hear otherwise.

        Show
        Rafael H. Schloming added a comment - This has sat for a while now, and there are various more specific JIRAs for other SSL issues, so I'm going to consider this fixed by the new route APIs until I hear otherwise.
        Hide
        Rafael H. Schloming added a comment -

        I've taken a stab at adding some functionality to the messenger API that addresses this area, namely the new pn_messenger_route API that I posted about on the list recently. The conversation above covers a wide range of topics though, so I'd like people to have a look at what I've done and let me know if there are still areas that need work for this JIRA, or if we can close it off and/or open some smaller/more specific JIRAs to address any remaining problem areas.

        Show
        Rafael H. Schloming added a comment - I've taken a stab at adding some functionality to the messenger API that addresses this area, namely the new pn_messenger_route API that I posted about on the list recently. The conversation above covers a wide range of topics though, so I'd like people to have a look at what I've done and let me know if there are still areas that need work for this JIRA, or if we can close it off and/or open some smaller/more specific JIRAs to address any remaining problem areas.
        Hide
        Rob Godfrey added a comment -

        I'm somewhat late to this party, but I am hitting this same issue in some work that I am doing. The solution I am looking for is, I think, that given by Gordon above - the ability to use configuration information such that Messenger resolves "hostname" to a TCP/IP address through custom configuration. In my use case I would have a single IP address that all hosts initially resolve to - this will be the "redirector" component. The redirector will then hold secondary configuration as to where the actual TCP/IP address to connect to is, and will send the redirect accordingly.

        Are we still looking to address this (excuse the pun) for 0.5?

        Show
        Rob Godfrey added a comment - I'm somewhat late to this party, but I am hitting this same issue in some work that I am doing. The solution I am looking for is, I think, that given by Gordon above - the ability to use configuration information such that Messenger resolves "hostname" to a TCP/IP address through custom configuration. In my use case I would have a single IP address that all hosts initially resolve to - this will be the "redirector" component. The redirector will then hold secondary configuration as to where the actual TCP/IP address to connect to is, and will send the redirect accordingly. Are we still looking to address this (excuse the pun) for 0.5?
        Hide
        Rafael H. Schloming added a comment -

        Ok, thanks for wading through my ramblings. I'll take a crack at this and post again when I have something concrete.

        Show
        Rafael H. Schloming added a comment - Ok, thanks for wading through my ramblings. I'll take a crack at this and post again when I have something concrete.
        Hide
        Affan Dar added a comment -

        I think the assumption behind option (1) was that adding a connection level setting (such as an alias) may not be appropriate for the level that the messenger API is operating it. Seems like that is not a big issue which is great. Connection aliasing is a good solution and will work for all scenarios (reconnect, redirect etc). It will also make the receive side more symmetric with the send side which is goodness.

        Show
        Affan Dar added a comment - I think the assumption behind option (1) was that adding a connection level setting (such as an alias) may not be appropriate for the level that the messenger API is operating it. Seems like that is not a big issue which is great. Connection aliasing is a good solution and will work for all scenarios (reconnect, redirect etc). It will also make the receive side more symmetric with the send side which is goodness.
        Hide
        Rafael H. Schloming added a comment -

        I was assuming auto-redirect was part of what was being asked for in PROTON-164, but if not we can split that into a separate Jira. I do think it would be good if we could make the redirect happen transparently, e.g. treat it as part of the resolution process.

        Regarding the semantics being discussed, I'm unclear on the need for two messages with the same address to connect to different physical endpoints. What I'm leaning towards is some way to explicitly specify the TCP endpoint for a given address, but not necessarily on a per message basis, rather just a per address basis. This would omit both the problematic redirector scenario and maintain the semantic that for a given messenger, a given address will always resolve to a single connection. I like maintaining this property because I think it's a simpler model for users and in particular the security model here maps strongly to the one used by web browsers. You only need to look in one place (the to field) to figure out where a message is going, and your certificates are always validated against that.

        To draw an analogy to a web browser, if the to field is the URL, then I think the approach option (1) is taking is basically adding another input field to your web browser UI that lets you override DNS lookup whenever you type in a URL. This would let you type in the same URL twice, and get completely different results depending on the value typed into this other field. What I'm suggesting with option (3) is pretty much like overriding your /etc/hosts file so whenever a given URL appears, it resolves to something you control, but it will always resolve to the same thing until you go change your hosts file. I think these both have equivalent capabilities, but I feel like option (3) is simpler for the scenarios where I can imagine needing this kind of thing.

        As an aside, I think this aliasing thing would also give us a path towards more advanced configurations, e.g. imagine adding wildcard support and you have an easy way to instruct a messenger to direct all (or some subset) of messages through a single broker, e.g. alias * -> my-broker, or alias *.foo -> my-broker and alias *.bar -> your-broker.

        Show
        Rafael H. Schloming added a comment - I was assuming auto-redirect was part of what was being asked for in PROTON-164 , but if not we can split that into a separate Jira. I do think it would be good if we could make the redirect happen transparently, e.g. treat it as part of the resolution process. Regarding the semantics being discussed, I'm unclear on the need for two messages with the same address to connect to different physical endpoints. What I'm leaning towards is some way to explicitly specify the TCP endpoint for a given address, but not necessarily on a per message basis, rather just a per address basis. This would omit both the problematic redirector scenario and maintain the semantic that for a given messenger, a given address will always resolve to a single connection. I like maintaining this property because I think it's a simpler model for users and in particular the security model here maps strongly to the one used by web browsers. You only need to look in one place (the to field) to figure out where a message is going, and your certificates are always validated against that. To draw an analogy to a web browser, if the to field is the URL, then I think the approach option (1) is taking is basically adding another input field to your web browser UI that lets you override DNS lookup whenever you type in a URL. This would let you type in the same URL twice, and get completely different results depending on the value typed into this other field. What I'm suggesting with option (3) is pretty much like overriding your /etc/hosts file so whenever a given URL appears, it resolves to something you control, but it will always resolve to the same thing until you go change your hosts file. I think these both have equivalent capabilities, but I feel like option (3) is simpler for the scenarios where I can imagine needing this kind of thing. As an aside, I think this aliasing thing would also give us a path towards more advanced configurations, e.g. imagine adding wildcard support and you have an easy way to instruct a messenger to direct all (or some subset) of messages through a single broker, e.g. alias * -> my-broker, or alias *.foo -> my-broker and alias *.bar -> your-broker.
        Hide
        Gordon Sim added a comment -

        I greatly prefer option (3) as outlined at the end of comment #1(https://issues.apache.org/jira/browse/PROTON-160?focusedCommentId=13505199), i.e. having some way to configure a messenger to handle addresses (falling back to DNS based resolution if no rules exist/apply). Per-message addresses should ideally be logical with a flexible mapping to the physical addresses over which they should then be transferred. Option 3 seems the safest and neatest solution.

        I find option 1 confusing as well as I think being to tied to a particular pattern of use. I thinks URLs are actually a less than ideal choice for the address syntax as they confuse the notions of (hierarchical) domain scoped logical naming with 'connection strings', and adding in various options and parameters is I think the thin end of the wedge that will lead to muddiness.

        Show
        Gordon Sim added a comment - I greatly prefer option (3) as outlined at the end of comment #1( https://issues.apache.org/jira/browse/PROTON-160?focusedCommentId=13505199 ), i.e. having some way to configure a messenger to handle addresses (falling back to DNS based resolution if no rules exist/apply). Per-message addresses should ideally be logical with a flexible mapping to the physical addresses over which they should then be transferred. Option 3 seems the safest and neatest solution. I find option 1 confusing as well as I think being to tied to a particular pattern of use. I thinks URLs are actually a less than ideal choice for the address syntax as they confuse the notions of (hierarchical) domain scoped logical naming with 'connection strings', and adding in various options and parameters is I think the thin end of the wedge that will lead to muddiness.
        Hide
        Affan Dar added a comment -

        Regarding the messenger resolution process, the following semantic is one possibility and seems to reflect what you are thinking as well:

        • message.network_host, if specified, is the physical address of the host. I.e. this is the destination end point for the TCP connection.
        • message.address is the "TLS endpoint" of the host which is used in open.hostname and SASL etc. Furthermore, if message.network_host is not specified then this will also be used as the destination end point for the TCP connection, i.e. the easy default that you mentioned.
        • Messages with the same message.address can have different values in message.network_host and the connections associated with the respective networkhosts would be used to send these messages.

        I think PROTON-136 can benefit from this by using the message.address as the key for the session cache.

        Furthermore, are there plans on adding auto-redirect to the resolution process? I think it raises some other questions. If there is a JIRA tracking that work then I can add some comments to it.

        Show
        Affan Dar added a comment - Regarding the messenger resolution process, the following semantic is one possibility and seems to reflect what you are thinking as well: message.network_host, if specified, is the physical address of the host. I.e. this is the destination end point for the TCP connection. message.address is the "TLS endpoint" of the host which is used in open.hostname and SASL etc. Furthermore, if message.network_host is not specified then this will also be used as the destination end point for the TCP connection, i.e. the easy default that you mentioned. Messages with the same message.address can have different values in message.network_host and the connections associated with the respective networkhosts would be used to send these messages. I think PROTON-136 can benefit from this by using the message.address as the key for the session cache. Furthermore, are there plans on adding auto-redirect to the resolution process? I think it raises some other questions. If there is a JIRA tracking that work then I can add some comments to it.
        Hide
        Rafael H. Schloming added a comment -

        I think this issue is related to a couple of others: PROTON-161, PROTON-90, and PROTON-136, and to some extent PROTON-164 (specifically the portion pertaining to redirect).

        The spec has the following language regarding the hostname field:

        "The name of the host (either fully qualified or relative) to which the sending peer
        is connecting. It is not mandatory to provide the hostname. If no hostname is provided
        the receiving peer SHOULD select a default based on its own configuration. This field
        can be used by AMQP proxies to determine the correct back-end service to connect
        the client to.

        This field MAY already have been specified by the <xref name="sasl-init"/> frame, if a
        SASL layer is used, or, the server name indication extension as described in
        RFC-4366, if a TLS layer is used, in which case this field SHOULD be null or contain
        the same value. It is undefined what a different value to that already specified
        means."

        Note in particular the relationship between the TLS hostname and this field.

        So PROTON-161/PROTON-90 have identified the need to somehow specify a name to match against the TLS certificate. I think there may be a requirement implicit in PROTON-136 to key the session cache off of something meaningful to the TLS layer, and of course we have this Jira. It sounds to me like these all fall under the general problem that the "TLS endpoint" needs to be able to be independent from the "TCP endpoint", although for obvious reasons it's desirable to make it easy (i.e. default them) to be the same.

        From what I can tell, it seems like the open.hostname field, the session key used for PROTON-136, and the name we match against the TLS certificate all should come from a single source. Right now that source is the message address. Assuming that is the right source for that info we need to specify exactly how to transform the address into this "TLS hostname" thing. This relates to PROTON-163, as that is pointing out a specific case where we are transforming incorrectly, but it would also be good to know how to handle other kinds of URLs as the URL syntax allows lots of random cruft in there and I don't know offhand what is supposed to be part of this canonical TLS hostname thingy and what isn't, e.g. if you do amqp://host:port/blah, is the port part of it or not? I'm guessing there's some possibly authoritative info out there we can crib from on what browsers do as this is essentially the same problem as transforming the typed-in URL into the HTTP "Host" header.

        Now as for this JIRA in particular, I think we need to understand the overall resolution process that messenger goes through when resolving the TCP connection info for a given message address, and this needs to somehow account for redirects as mentioned in PROTON-164. Right now messenger will do a DNS lookup on the host portion of the message address in order to determine the TCP endpoint, however it only does this the first time it encounters a message to a given address. All subsequent messages to the same address will get sent down the same connection that was established by the first message for as long as that connection survives. Now assuming we transparently handle redirects as simply a further step in the resolution process, then I would expect this scenario to extend pretty well. On the first message we'd do the DNS lookup, connect to a redirector, and then establish a permanent connection and send all subsequent messages there. What's not clear to me though is how this would interact with option (1). If we're specifying a network address to connect to on a per message basis, then what happens if we have already have an existing connection for the address specified in this message, and this existing connection doesn't match the supplied network address? If we use the existing connection then I would say we aren't really specifying network connectivity on a per message basis, we're actually just short-circuiting/overriding the resolution process, i.e. this is equivalent to simply configuring a set of aliases for the messenger, e.g. when you see address "foo", make your TCP connection to "bar". On the other hand if we don't use the existing connection we could end up with some pathological behaviour if you point your message to a redirector since we would end up making a new connection for every single message we send.

        Apologies for the long and rambling post, I probably shouldn't have tried to tackle this one so late. I guess I'll just wrap up by asking A) does any of the above make sense, and B) do you have any more info on the overall scenario you're trying to support, and C) is it worth investigating some kind of option (3) along the lines of the aliasing mentioned above?

        Show
        Rafael H. Schloming added a comment - I think this issue is related to a couple of others: PROTON-161 , PROTON-90 , and PROTON-136 , and to some extent PROTON-164 (specifically the portion pertaining to redirect). The spec has the following language regarding the hostname field: "The name of the host (either fully qualified or relative) to which the sending peer is connecting. It is not mandatory to provide the hostname. If no hostname is provided the receiving peer SHOULD select a default based on its own configuration. This field can be used by AMQP proxies to determine the correct back-end service to connect the client to. This field MAY already have been specified by the <xref name="sasl-init"/> frame, if a SASL layer is used, or, the server name indication extension as described in RFC-4366, if a TLS layer is used, in which case this field SHOULD be null or contain the same value. It is undefined what a different value to that already specified means." Note in particular the relationship between the TLS hostname and this field. So PROTON-161 / PROTON-90 have identified the need to somehow specify a name to match against the TLS certificate. I think there may be a requirement implicit in PROTON-136 to key the session cache off of something meaningful to the TLS layer, and of course we have this Jira. It sounds to me like these all fall under the general problem that the "TLS endpoint" needs to be able to be independent from the "TCP endpoint", although for obvious reasons it's desirable to make it easy (i.e. default them) to be the same. From what I can tell, it seems like the open.hostname field, the session key used for PROTON-136 , and the name we match against the TLS certificate all should come from a single source. Right now that source is the message address. Assuming that is the right source for that info we need to specify exactly how to transform the address into this "TLS hostname" thing. This relates to PROTON-163 , as that is pointing out a specific case where we are transforming incorrectly, but it would also be good to know how to handle other kinds of URLs as the URL syntax allows lots of random cruft in there and I don't know offhand what is supposed to be part of this canonical TLS hostname thingy and what isn't, e.g. if you do amqp://host:port/blah, is the port part of it or not? I'm guessing there's some possibly authoritative info out there we can crib from on what browsers do as this is essentially the same problem as transforming the typed-in URL into the HTTP "Host" header. Now as for this JIRA in particular, I think we need to understand the overall resolution process that messenger goes through when resolving the TCP connection info for a given message address, and this needs to somehow account for redirects as mentioned in PROTON-164 . Right now messenger will do a DNS lookup on the host portion of the message address in order to determine the TCP endpoint, however it only does this the first time it encounters a message to a given address. All subsequent messages to the same address will get sent down the same connection that was established by the first message for as long as that connection survives. Now assuming we transparently handle redirects as simply a further step in the resolution process, then I would expect this scenario to extend pretty well. On the first message we'd do the DNS lookup, connect to a redirector, and then establish a permanent connection and send all subsequent messages there. What's not clear to me though is how this would interact with option (1). If we're specifying a network address to connect to on a per message basis, then what happens if we have already have an existing connection for the address specified in this message, and this existing connection doesn't match the supplied network address? If we use the existing connection then I would say we aren't really specifying network connectivity on a per message basis, we're actually just short-circuiting/overriding the resolution process, i.e. this is equivalent to simply configuring a set of aliases for the messenger, e.g. when you see address "foo", make your TCP connection to "bar". On the other hand if we don't use the existing connection we could end up with some pathological behaviour if you point your message to a redirector since we would end up making a new connection for every single message we send. Apologies for the long and rambling post, I probably shouldn't have tried to tackle this one so late. I guess I'll just wrap up by asking A) does any of the above make sense, and B) do you have any more info on the overall scenario you're trying to support, and C) is it worth investigating some kind of option (3) along the lines of the aliasing mentioned above?

          People

          • Assignee:
            Rafael H. Schloming
            Reporter:
            David Ingham
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development