-
Notifications
You must be signed in to change notification settings - Fork 184
Fix hostname resolution for proxied connections #913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@bartosz822 I'm inclined to approve this, but first...
|
InetSocketAddress address = new java.net.InetSocketAddress("www.example.com", 80);
System.out.println(address.getAddress()); // www.example.com/93.184.216.34
System.out.println(address.getHostName()); // www.example.com
System.out.println(address.isUnresolved()); // false
InetSocketAddress addressUnresolved = java.net.InetSocketAddress.createUnresolved("www.example.com", 80);
System.out.println(addressUnresolved.getAddress()); // null
System.out.println(addressUnresolved.getHostName()); // www.example.com
System.out.println(addressUnresolved.isUnresolved()); // trueNote: if (epoint.isUnresolved())
impl.connect(addr.getHostName(), port);
else
impl.connect(addr, port);
|
|
@bartosz822 Just waiting for another pair of eyes on this. |
|
@bartosz822 I'm closing this, it's redundant. If you trace back, you can see it's already done before it gets here. Look at the code around NatsConnection, line 207. |
|
@scottf I've seen the code you've mentioned and this pull request is not redundant, could you please reopen it? I've observed in proxy logs using this library that the connection was made using the IP address even though Take also a look at the implementation of |
|
What was the input, meaning the servers specified in the options? You saw the stack trace. Also, if there is any resolving or checking to be done, it needs to be done before SocketDataPort.connect. I suppose it's possible that the SocketDataPort may need to be changed to never resolve as it should take exactly what it was given |
Only one server was specified, in the format
It's not |
|
Reopening... this conversation is good, getting us to where we need to be. Thanks for the input. |
|
@scottf thanks for reopening, what are the next steps now? |
|
@scottf I haven't received any new feedback on this PR since quite a while. Is it ok? Is there something else that needs to be done? |
|
@bartosz822 Sorry you are just going to have to be patient, I'm juggling several priorities right now and the behavior is under discussion. |
|
Hi, I was curious how we're doing on this MR? The reason that I'm asking is that we currently have to maintain some firewall rules using IP addresses over domain names which the colleagues from security don't like much. |
It's been quite a while since I reviewed this but I remember it was incomplete. Resolve hostnames is on by default, but you can turn it off in options via the options builder by calling noResolveHostnames() |
|
Looking at the description it seems that the |
|
@GrafBlutwurst I think the problem is legitimate, just not the fix in this PR. Also, why are you proxying connections? |
|
@GrafBlutwurst I really wanted to close this but the user insisted I was not understanding the problem. Which may be true. Is it possible that you can open a fresh defect issue in the repo and we can try to start this process over? I'm certain, I was not happy with the proposed code change, but frankly it's been a while and I can't remember why. |
So the reason for proxying is sadly out of our hands. The connection lives at customer site and they require proxied connections for compliance reasons. We actually specifically chose NATS for the websocket & proxying capabilities for this reason. |
If I remember correctly, by the time it got to that point, it should have already been resolved. So it needs to be traced back and determined where it should happen. |
|
I think the point here is that in a proxied case with firewalls we never want the hostname to be resolved to an IP on the client. Connections should always be established by hostname so that we don't need 2 firewall rules. In particular the constructor call At least that was my understanding when looking at the code and would address our issue with hostname resolution. |
|
@GrafBlutwurst Is this still an issue? Recent versions of the client support proxies much better, addressing the fact that the client to proxy is secure, but commonly proxy to server is insecure. Also there is the Options.noResolveHostnames option. |
|
A recent development. The consensus is that for WebSocket, I should never do the host IP resolution and they actually consider it a "bug" in the Java client. It's been fixed here #1286 |
|
The issue still persists on the latest version of jnats, the changes in this PR however fix it. The resolution is performed by the InetSocketAddress constructor and the only way to not do it is to use |
|
@bartosz822 Opening and I will look at this again but 2 things.
You will also need to rebase / resolve conflicts. |
…aining an IP address
cf99e90 to
465b0e6
Compare
| socket.connect(new InetSocketAddress(host, port), (int) timeout); | ||
| InetSocketAddress inetSocketAddress = (options.isNoResolveHostnames() && !nuri.hostIsIpAddress()) ? | ||
| InetSocketAddress.createUnresolved(host, port) : new InetSocketAddress(host, port); | ||
| socket.connect(inetSocketAddress, (int) timeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, resolution is supposed to be done before it gets here. Look in the NatsConnection line 540 and work backward. Also look in NatsServerPool, where it does resolveHostToIps.
Resolution does not belong here, it belongs further back up the call chain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the resolution probably belongs further back up the call chain. However the problem is that even if it didn't happen earlier, the default constructor of InetSocketAddress will perform it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be correct to say that this is only an issue in some cases AND only when a proxy is provided?
Why can't the proxy be expected to do this work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it is an issue only in some cases, it only really is an issue if a proxy is doing whitelisting based on domain names, which is a common use-case in secure/enterprise environments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the question remains, why can't this be part of the Option.proxy's responsibility? If it can be, we can simply add documentation to that effect.
I'm suspicious how common this really is in secure/enterprise environments. Enterprises are the most common users of this client, it's been around for 7 years, and this is the first time I'm hearing about the issue.
At a minimum we need an opt in solution to ensure backward compatibility, like isEnableInetAddressCreateUnresolved or something like that.
if (options.isEnableFastFallback()) {
socket = connectToFastestIp(options, host, port, (int) timeout);
}
else {
InetSocketAddress inetSocketAddress;
if (options.isEnableInetAddressUnresolved() && !nuri.hostIsIpAddress()) {
inetSocketAddress = InetSocketAddress.createUnresolved(host, port);
}
else {
inetSocketAddress = new InetSocketAddress(host, port);
}
socket.connect(inetSocketAddress, (int) timeout);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bartosz822 bump
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the suggested option.
I don't understand how it could be part of the Option.proxy responsibility? What do you mean by that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The proxy seems to have some flexibility. You test has a proxy implementation. It seems like code could just go in there. But at least there is a backward compatible way now, so I think that's fine.
|
Is there a way to reproduce this with a unit test, or at least document something reproducible? |
|
I've added a unit test to showcase the issue. The test fails without the changes in |
Proxied connections resolve the hostname to an IP address while tunneling even when noResolveHostname option is set.
This behavior is unwanted in some scenarios, especially when a proxy does whitelisting based on hostnames.
This pr should fix this.