how to customize the ribbon load balancer in Zuul server - netflix-zuul

As I understand the default load balancer using in Zuul proxy server as DynamicServerListLoadBalancer and it use ZoneAffinityServerListFilter rule to choose server. However, is there any way I can customize the loadbalancer used in zuul proxy server
I have tried to add following configuration to change to loadbalancer Rule:
eureka.client.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
But seems it still stick with default configuration.
Any advice is highly appreciated.

To change load balancing rule with configuration, you should define ribbon configuration like below.
your_ribbonclient_name.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
your_ribbonclient_name shoud be replaced with the proper one for your configuration. In Zuul, ribbon client name is same with service id for each route.
You can also provide your own IRule bean for load balancing rule with #RibbonClient like the following.
#RibbonClient(name = "your_ribbonclient_name", configuration = YourConfigurationClass.class)
You can find an example code here
If you want to apply your Ribbon config to whole ribbon clients in your server,
you can do that with #RibbonClients (not #RibbonClient).
#RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
You can find the example code here, and the related issues is here.

Related

Ingress Controller in AKS (Application Gateway) / Define custom names for http settings and rules

I have deployed an application gateway with ingress controller for my AKS Cluster.
Once I deploy the ingress resource the underlaying resources are then visible in the Azure portal like listner, http settings,rule, etc.
My "problem" is that I would like to have more controll over the respective names of the rules and http settings.
The names that Azure is using for the respective http settings and rule names, are a bit unclear when there are multiple such http settings, rules and listners. The names that azure used are for example like this:
Listener: fl-e1903c8aga3446b783607aec6d6ecba8a
Rule: rr-u1903c8aa8446b8b32078ec6d6ecba8a
Having it like this, makes it extreemly difficult to keep track which is which.
I have looked in the doku [1] and [2] but I wasnt able to find an option where I could set this up in the ingress resource.
Do you have any idea where can I set this up, if at all?
Thank you,
Mike
[1] https://azure.github.io/application-gateway-kubernetes-ingress/
[2] https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-expose-service-over-http-https

How to configure a reverse proxy for multiple IIS sites and a single IP?

I've inherited some internal sites from a previous employee and my constraints are the following, it is written in MVC and I need to change how it is hosted and no direct control over DNS. Security won't allow me to use subdomains within DNS so I'd like to use a subdomain within IIS or file path extension. manage.mgmt.domain.td or mgmt.domain.td/manage as an example.
How can I configure an IIS binding and an inbound proxy rule so that mgmt.domain.td directs to a general menu page, but manage1.mgmt.domain.td directs to a separate page and manage2.mgmt.domain.td to another page and have them fully functional. I've been able to configure the inbound reverse proxy rule to use an IP such as 10.0.0.1:801, however I cannot configure it to working using either friendly format listed above.
Can a vdir, appdir, work with an mvc project or is a reverse proxy better? It's iis10 .
https://computingforgeeks.com/configure-virtual-directory-on-windows-iis-server/
[Edit adding IIS binding and reverse proxy rule image]
Current
ASP.NET applications run in application pool. When you add vdir, you cannot choose application pool. So add application is more suitable than vdir.
I can type in the ip 10.0.0.1/manage and it points to my site, I can also type 10.0.0.1 and it will load the same content (which I dont' want)
10.0.0.1/manage is the correct url to access MVC application. If 10.0.0.1 also show same content, consider that client cache or url redirect. The correct content it shows should be index page of the main site.
however it is not loading content when I use the dns friendly name?
I cannot understand what the dns friendly name you mean. If you have a public domain name, just bind the domain to the server in server provider. and when you add site, set the host name to it.
An easier way to do this is to add a route to your application, for example on global.asax, to get the incoming server address from there and direct it to the correct destination. For Application_Begin_Request in Mvc, you can refer to this article here.

Spring Cloud Load Balancer - Custom Load Balancer Client config through Java

Specifying custom configuration for load balanced services is possible through the use the "LoadBalancerClient" & "LoadBalancerClients" annotations as illustrated below.
https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#custom-loadbalancer-configuration
How can we specify the same config through Java? We have a case where the services can increase dynamically and we don't want to keep modifying code to add them. Their load balancer configs will remain similar except for the service instances. We are looking to add a generic custom config which can then return the supplier list depending on the service name.
Declaring a bean of type LoadBalancerClientFactory containing the list of all applicable LoadBalancerClientSpecification did the trick.
Pretty straightforward but had to dig around to figure out which bean to expose as there was no example that I could find.

Pivotal CloudFoundry: Enforcing HTTPS (SSL)

I want to enforce HTTPS for a Spring Boot application to be hosted at Pivotal CloudFoundry, and I think most of the applications would want this today. The common way of doing it, as I know, is using
http.requiresChannel().anyRequest().requiresSecure()
But this is causing a redirect loop. The cause, as I understand by refering to posts like this, is that the load balancer converts back https to http. That means, it has to be done at the load balancer level.
So, is there some option to tell CloudFoundry to enforce HTTPS for an application? If not, shouldn't this be a feature request? And, what could be a good way to have this today?
Update: Did any of you from Cloud Foundry or Spring Security team see this post? I think this is an essential feature before one can host an application on CloudFoundry. Googling, I found no easy solution but to tell the users to use https instead of http. But, even if I tell so, when an anonymous user tries to access a restricted page, Spring Security is redirecting him back, to the http login page.
Update 2: Of course, we have the x-forwarded-proto header as many answers suggest, but I don't know how hard it would be to customize the features of Spring Security to use that. Then, we have other things like Spring Social integrating with Spring Security, and I just faced an issue there as well. I think either Spring Security and tons of other other frameworks will need to come out with solutions to use x-forwarded-proto, or CloudFoundry needs to have some way to handle it transparently. I think the later would be far convenient.
Normally, when you push a WAR file to Cloud Foundry, the Java build pack will take that and deploy it to Tomcat. This works great because the Java build pack can configure Tomcat for you and automatically include a RemoteIpValve, which is what takes the x-forwarded-* headers and reconfigures your request object.
If you're using Spring Boot and pushing as a JAR file, you'll have an embed Tomcat in your application. Because Tomcat is embedded in your app, the Java build pack cannot configure it for the environment (i.e. it cannot configure the RemoteIpValve). This means you need to configure it. Instructions for doing that with Spring Boot can be found here.
If you're deploying an web application as a JAR file but using a different framework or embedded container, you'll need to look up the docs for your framework / container and see if it has automatic handling of the x-forwarded-* headers. If not, you'll need to manually handle that, like the other answers suggest.
You need to check the x-forwarded-proto header. Here is a method to do this.
public boolean isSecure (HttpServletRequest request) {
String protocol = request.getHeader("x-forwarded-proto");
if (protocol == null) {
return false;
}
else if (protocol.equals("https")) {
return true;
}
else {
return false;
}
}
Additionally, I have created an example servlet that does this as well.
https://hub.jazz.net/git/jsloyer/sslcheck
git clone https://hub.jazz.net/git/jsloyer/sslcheck
The app is running live at http://sslcheck.mybluemix.net and https://sslcheck.mybluemix.net.
Requests forwarded by the load balancer will have an http header called x-forwarded-proto set to https or http. You can use this to affect the behavior of your application with regard to SSL termination.

Spring Webapp behind Apache Web Server - Secured by CAS

I have a Webapp that is secured using Spring Security CAS. The CAS Server and the Webapp sit behind a web server for reverse proxy (named url). The webapp uses ServiceAuthenticationDetailsSource to authenticate dynamic service urls. The problem I have is that Service Ticket validations are failing because the url supplied during validation does not match the url provided when the ticket was created. The set up works without the webserver when systems are connected using https://:/.
The issue seems to be that the web server modifies the HttpServletRequest when redirecting to the webapp where in it looses the "named url" information and is substituted with the and . The service ticket is obtained using the named url via "?service=" during login.
Any possible solution? Can apache reroute request without modifying it, especially for applications that are self identifying or for security reasons where CAS is trying to record the client IP address?
I have outlined a few options below:
Setup the Reverse Proxy
According to the Javadoc of ServletRequest: the HttpServletRequest.getServerName() will be:
the value of the part before ':' in the Host header value, if any, or
the resolved server name, or the server IP address.
This means you can configure your proxy to ensure the Host Header is set properly (Note Some containers like WebSphere do not honor the specification though).
Override using the Container Configuration
Many servers have a setup that can override this value in the event you are using a reverse proxy. There is a pretty decent thread on the Spring forums with a bit more information on it that I have summarized below.
If you are using Tomcat, I'd refer to the Reverse Proxy setup page. One method of configuration would be to configure the Http Connector to have the proxyName attribute to override the value returned by HttpServletRequest.getServerName() and proxyPort to override the value returned by HttpServletRequest.getServerPort(). An example configuration might look like:
server.xml
<Connector scheme="https" secure="true"
proxyPort="443" proxyName="example.com"
port="8009" protocol="AJP/1.3"
redirectPort="8443" maxThreads="750"
connectionTimeout="20000" />
Websphere has a few custom properties that do the same thing.
com.ibm.ws.webcontainer.extractHostHeaderPort = true
trusthostheaderport = true
httpsIndicatorHeader = com.ibm.ws.httpsIndicatorHeader
If you are not using either of these containers or need to support multiple domains, you will need to consult your containers documentation.
Custom AuthenticationDetailsSource
Of course Spring Security is pretty flexible, so you can always provide a custom implementation of AuthenticationDetailsSource that returns an instance of ServiceAuthenticationDetails that looks up the service URL in any way you wish.

Resources