Accept Proxy Protocol V2 Traffic with Jetty in Spring Boot - java

I am trying to configure Jetty 9.4.39.v20210325 in java Spring Boot 2.4.5 to accept proxy protocol V2 traffic. I want to do this programmatically in a spring configuration class. This is the method I wrote in the SharedConfiguration.java configuration class based on the Proxy Protocol section on the bottom of this page.
#Bean
public ConfigurableServletWebServerFactory
jettyCustomizer() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.addServerCustomizers(server -> {
ProxyConnectionFactory proxyConnectionFactory = new ProxyConnectionFactory();
ServerConnector serverConnector = new ServerConnector(server, proxyConnectionFactory);
server.addConnector(serverConnector);
});
return factory;
}
The HTTP traffic is coming from an AWS EC2 network load balancer (NLB) and the balancer has proxy protocol V2 traffic enabled.
I am getting this response when I activate an endpoint in my service with the proxy protocol traffic:
Bad Message 400
reason: Illegal character CNTL=0x0
Does anyone know how I can get my service to accept this proxy protocol V2 traffic? I'm unsure if I am configuring Jetty correctly to do so.
Thanks!

I have since figured out the problem with my configuration, I was adding a new server connector instead of changing the one already in the Jetty server.
Here is the correct approach:
#Bean
public ConfigurableServletWebServerFactory jettyCustomizer() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.addServerCustomizers(server -> {
ServerConnector serverConnector = (ServerConnector) server.getConnectors()[0];
serverConnector.addFirstConnectionFactory(new ProxyConnectionFactory());
});
return factory;
}
Here I am getting the active server connector and mutating it to also contain a ProxyConnectionFactory which allows Jetty to accept the proxy protocol traffic.

Related

Connect to remote instance of Elasticsearch through spring data elasticsearch using an URL

I'm very newbie to ES and I'm having a lot of troubles to connect to an external instance od ES through my java web app, let's say that I have the following client config
#Configuration
#ComponentScan(basePackages = {"com.elasticsearchlogs.elasticsearchlogsbackend"})
public class Config extends AbstractElasticsearchConfiguration {
#Value("${elasticsearch.url}")
public String elasticsearchUrl;
#Bean
#Override
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration config = ClientConfiguration.builder()
.connectedTo(elasticsearchUrl)
.build();
return RestClients.create(config).rest();
}
}
When I was making some tests with elastichsearchUrl = "localhost:9200" all was fine, but know i should connect to an ES instance that is in a external server, that is accesible, let suppose by the following url https://elasticinstance.com (yes it uses Https).
The problem is that if a put the url like in the example, java complains because it asks for a port number. I don't really know what port number have I to give it, I have tried with 9300 and 9200 because they are the default ports in ES, also with 443 because is the default port in Https.
What should I do? Shall I ask my admin to give me a port number to connect? Or shall I configure the client in any special way?
I think as you are trying to connect to external Elasticsearch server with Https, first
Go through, https://www.elastic.co/blog/configuring-ssl-tls-and-https-to-secure-elasticsearch-kibana-beats-and-logstash, this tells you how to Create SSL certificates and enable TLS for Elasticsearch.
Then you can try and access Elasticsearch with https://[ip/domainname:port].com
Or to validate first if everything is OK with current setup
Just access the server only with HTTP instead of HTTPS.

Upload files to AWS S3 using Spring Boot works fine without Proxy but fails with Proxy

Uploading files to AWS S3 using spring boot works great when it executed without proxy and when I add proxy in the VM args it fails with following error,
Internal Server Error (Service: Amazon S3; Status Code: 500; Error Code: 500 Internal Server Error; Request ID: null; S3 Extended Request ID: null; Proxy: 192.168.1.171)
Below are the vm arguments that I have provided,
-Dhttp.proxyHost=192.168.1.171 -Dhttp.proxyPort=9999 -Dhttps.proxyHost=192.168.1.171 -Dhttps.proxyPort=9999
When I started to execute the package the AWS SDK auto initialize the proxy as it finds in the args list
and it prints in the console
com.amazonaws.http.AmazonHttpClient - Configuring Proxy. Proxy Host: 192.168.1.171 Proxy Port: 9999
I can not remove the proxy because I am using Oauth2 authentication in spring security.
Is there any way that I can disable auto initializing the proxy in AWS SDK?
In effect to communicate over a network "endpoints" are an address, but links require "connections" so it may be more of a connection/connected "host conflict" by configuration.
For example i could have both a webserver and a DB that takes requests via http direct but it depends if they are configured for each other and/or to be connected through an irq to network to anything else.
I was able to resolve the issue after contacting AWS, I had to configure the method “setNoneProxyHosts (String nonProxyHosts)” method in the ClientConfiguration class. This sets the optional hosts the client will access without going through the proxy.
The parameter – “nonProxyHosts” takes the hosts the client will access without going through the proxy. Please follow this link here for more information about the class and the method: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ClientConfiguration.html#setNonProxyHosts-java.lang.String-
Based on the instructions provided by AWS Support I had amended the config and added following;
public ClientConfiguration clientConfiguration() {
final ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setNonProxyHosts("*.s3.<ZONE>.amazonaws.com|*.s3-<ZONE>.amazonaws.com");
return clientConfiguration;
}

GSS_S_CONTINUE_NEEDED with apache http client

I'm trying to setup up an http client to authenticate with spnego (apache http client 4.5.2)
Here's the code that setups the client
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
final CredentialsProvider credsProvider = new SystemDefaultCredentialsProvider();
credsProvider.setCredentials(new AuthScope(null, -1, null), new KerberosCredentials(null));
final HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultCredentialsProvider(credsProvider);
final ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(builder.build());
final Client client = new ResteasyClientBuilder().httpEngine(engine).build();
On the server, I have a JAX-RS service which is sitting behind a waffle.servlet.NegotiateSecurityFilter to allow for ntlm or spnego authentication.
When I send my HTTP request from my chrome rest client, it works, authentication is successfully completed using negotiate.
When I try and use the apache http client however, it fails with the message in the log:
2018-03-05 16:47:16,048 DEBUG o.a.h.impl.auth.GGSSchemeBase main Authentication already attempted
2018-03-05 16:47:16,048 DEBUG o.a.h.i.auth.HttpAuthenticator main Authentication failed
After some further investigation I've discovered that the waffle filter is encoutingering GSS_S_CONTINUE_NEEDED and responding with an additional challenge which the apache client is simply ignoring and giving up on.
I've tested my apache client setup against another service which uses spnego (provided by a 3rd party) and it works properly, although doesn't employ the continue token.
I'm not sure if my system is setup incorrectly, and that the continue token shouldn't be happeneing or if the apache http client is improperly configured (or doesn't support continue tokens at all)
There's a very old ticket here https://issues.apache.org/jira/browse/HTTPCLIENT-1107 indicating that something was added to handle additional challenges, but from reading the code in org.apache.http.impl.auth.GGSSchemeBase.parseChallenge(CharArrayBuffer, int, int) it looks as though only the first challange is ever accepted.

Does OkHttp3 support HTTP2 via a HTTP forward proxy?

I am using OkHttp3 in my Android app to make HTTP/1.x requests to my backend servers via a forward proxy, like so:
List<Protocol> protos = new ArrayList<>();
protos.add(Protocol.HTTP_2);
protos.add(Protocol.HTTP_1_1);
InetSocketAddress proxyAddr = new InetSocketAddress("proxy.example.com", 80);
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddr);
OkHttpClient cli = new OkHttpClient.Builder()
.proxy(proxy)
.protocols(protos)
.build();
String url = "http://www.example.com/";
Request req = new Request.Builder().url(url).build();
Response res = cli.newCall(req).execute();
I would like to upgrade to HTTP2. However, it seems to me that OkHttp3 can make HTTP2 requests only if we are not going via a HTTP proxy. So, the above code wouldn't work.
In other words, OkHttp3 supports the first 3 cases below but not the fourth. HTTP/2 below means h2 (HTTP/2 over TLS) not h2c (HTTP/2 over clear text).
a) client <-- HTTP/1.x --> upstream server
b) client <-- HTTP/1.x --> forward proxy <-- HTTP/x --> upstream server
c) client <-- HTTP/2 --> upstream server
d) client <-- HTTP/2 --> forward proxy <-- HTTP/x --> upstream server
Does anyone confirm or deny my understanding? Thanks.
OkHttp will do HTTP/2 over an HTTP proxy. You’ll need HTTPS on the server since OkHttp doesn’t implement plaintext HTTP/2.
Jesse, I tried retrieving https://www.google.com/ with Proxy.Type.HTTP via nghttp2's forward proxy nghttpx, which supports HTTP2 over TLS. Unfortunately, TLS handshaking did not happen and the forward proxy reported the following error.
... tls: handshake libssl error: error:1407609B:SSL routines:SSL23_GET_CLIENT_HELLO:https proxy request
From what I gather, this error means that okhttp3's proxy code is not doing TLS handshaking with the forward proxy.
This makes me think that HTTP2 over TLS via a forward proxy is kind of pointless, because the forward proxy won't be able to add any value to encrypted requests - the forward proxy is just a pass-through pipe. In fact, I think TLS via any forward proxy is pointless. End-to-end HTTP2 over TLS does make sense, but via a forward proxy doesn't.

Tomcat to talk to proxy server

I have an application deployed on tomcat in linux rhel 5 , now this application makes an external call to internet and my server is behind the proxy server , now how do I configure the tomcat server for it to understand the proxy.
Is there a configuration I can do to redirect all requests send by tomcat to external servers
Also to mention that I did make the entries into catalina.properties
http.proxyHost=
http.proxyPort=8080
Alternatively, configure them as VM parameters in catalina.bat.
-Dhttp.proxyHost=<> -DproxyPort=8080
Another approach would be to configure them at the application level. If you are using java's own api to invoke external url, the proxy could be set as follows. In case you are using another library like apache httpclient, it provides methods to configure the proxy.
SocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Type.HTTP, proxyAddress);
URL url = new URL(externalURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);

Categories

Resources