400 Bad Request load balancer for Apache servers with NGINX - apache

I am using NGINX as load balancer for Apache WebServers (WordPress). All servers are made with AWS EC2. My config for NGINX:
cat /etc/nginx/sites-available/default
upstream web_backend {
server 35.157.101.5;
server 35.156.213.23;
}
server {
listen 80;
location / {
proxy_pass http://web_backend;
}
}
But after NGINX restart i am access load balancer via public ip and getting an error:
Bad Request
Your browser sent a request that this server could not understand.
Additionally, a 400 Bad Request error was encountered while trying to
use an ErrorDocument to handle the request.
Apache/2.4.29 (Ubuntu) Server at
ip-172-31-35-36.eu-central-1.compute.internal Port 80
If i refresh page i am getting same error but with another ip in the end (second server’s private ip), so i understand that NGINX do the work and it is Apache problem.
I tried to add 80 port for my servers in nginx config, replace ips with dns and private ip, but it didn’t help. Access log on Apache doesn’t show anything useful, just 400 errors.
What could be the problem?

Don’t use ‘_’ for upstream name, it was the only reason for my problem.

Just check on which ports are the Apache WebServers Running. You have to add those to your upstreams.
E.g.:
upstream web_backend {
server 35.157.101.5:8080; //assuming that your apache webserver is running on this port on this host
server 35.156.213.23:3000;//And a different port on the other.. you still need to add them here if your ports are same
}

Related

Nginx reverse proxy to https location causes ssl_error_rx_record_too_long

ttI am adding an nginx reverse proxy in front of my existing nextcloudpi server in order to be able to route traffic to different servers in my network depending to the domain that is used. Currently the nextcloudpi server is the only one running, so all traffic is directly routed to it.
The server is only accessible via https and letsencrypt handles the certifactes on the nextcloudpi server.
In order to route traffic from my reverse proxy to the nextcloudpi server via https, I have set up the default.conf file to look like this:
server {
listen 443;
listen [::]:443;
server_name <my-public-url>;
location / {
proxy_pass https://<hostname-of-my-nextcloudpi-server>;
}
}
Unfortunately that doesn't work. Firefox returns SSL_ERROR_RX_RECORD_TOO_LONG and Chrome ERR_SSL_PROTOCOL_ERROR
I have also not seen anywhere where traffic is proxied to a https location. I am aware that in my internal network I can and should just route to the target location on port 80 but since the server is already set up to use https I want to keep it that way.
Thanks for your help

How to make nginx passthrough on 443 and redirect 80 to 443?

I have a winstone server (Jenkins) listening on 8443.
Jenkins has a valid cert, and Jenkins is doing the cert termination successfully:
JENKINS_ARGS="--httpPort=-1 --httpsKeyStore=/secure/jenkins.keystore --httpsKeyStorePassword=MY_PASSWORD --httpsPort=8443"
The only problem is that users now have to go:
https://example.com:8443
I don't want that port number in the URL.
I want:
https://example.com:8443 -> https://example.com
https://example.com -> https://example.com
http://example.com -> https://example.com
So I figure I'll run nginx on the same instance that is running Jenkins.
So my question is:
Do I have to reconfigure jenkins to NOT do cert termination so that nginx does it only?
Can nginx redirect 80 and 443 to localhost:8443 without a cert (Since Jenkins is doing cert termination)?
Do BOTH nginx AND Jenkins need to do cert termination?
Sorry for those similar questions.
I'm pretty sure an AWS ELB cannot replace what nginx is doing here, but I thought I'd throw it out there, in case an ELB can solve this for me too.
1) No, you can have Nginx Stream the connection directly to the Jenkins using the Stream Module.
Do note this was added in 1.9.0 but is not part of the default build so you might have to build it yourself.
It works a lot like an http server block but you have to set it up outside of the http block.
stream {
upstream jenkins_server {
server jenkins:443;
}
server {
listen 443;
proxy_pass jenkins_server;
}
}
2) You do not need a cert on nginx but you should have a http server block for port 80 that does a 301 to the 443 stream talked about in answer part 1.
server {
listen 80;
server_name your_server_name_here;
return 301 https://$host$request_uri;
}
3) No, you don't as you can use the nginx stream to passthru the ssl from the client to the Jenkins server.

Application Load Balancer + Nginx http to https redirect gives 502 Bad Gateway

What I try to do is very simple, I am using AWS application load balancer, and I want to redirect all my http requests to https:
I have the following setup:
An application load balancer (ALB1) which has two listeners:
HTTP:80
HTTP:443
Both rules are forwarding to a target group (TG1) in which 1 target instance is registered on both port 80 and 443, and both healthy.
and my nginx conf has the following setup:
server {
listen 80;
server_name {{server_name}};
access_log /var/log/nginx/http_redirect.log;
return 301 https://$server_name$request_uri;
}
server {
server_name {{server_name}};
listen 443 ssl default_server;
...
...
}
However, when I go to http://server_name/ping, I expect it to be redirected to https://server_name/ping, but I just got a 502 Bad Gateway, and I checked the log /var/log/nginx/http_redirect.log, it shows something like:
172.xx.xx.xx - - [13/Oct/2017:22:31:13 -0700] "\x16\x03\x01\x00\xA5\x01\x00\x00\xA1\x03\x03|\xFE\xC1\x88\x9E\xC88\xF8\xCDLn\xBAV,\xCE\xAF\xAA\xF2\x9Axv\x16\xD0\xC2\xE6\xFBE\x95oi%\x01\x00\x00(\xC0+\xC0/\xC0#\xC0'\xC0\x09\xC0\x13\xC0,\xC00\xC0$\xC0(\xC0\x14\xC0" 400 181 "-" "-"
another strange thing is if I refresh the page again, it gives the result without being redirected, and then refresh again, I will get 502 Bbad Gateway again, basically, I will get 502 Bad Gateway and result without redirect alternately. FYI, there is nothing in my nginx error log.
More observation: when I get correct response without redirecting, $remote_addr shows the IP of my vpn, and when I get 502, $remote_addr show another different IP.
Could anyone help?
Thanks
I finally figured out what is wrong, the way I set up my application load balancer was not exactly right, I cant have only 1 target group (TG1) in which 1 target instance is registered on both port 80 and 443. I need to setup 2 different target groups, 1 registered with port 443 and another 1 registered with port 80.

HTTPS proxy with caddy

I am working with a Golang app and Caddy as the HTTP server. The golang app rejects every http connection, it only can be used over HTTPS. This app is a kind of API/service that is consumed by other apps. As, it requires HTTPS I installed Caddy so I can take advantage of the automatic SSL certificate and use proxy to switch between the ports.
The application is running in the port 9000, so, the consumers will only writte mysite.com and caddy should be in charge of redirect that petitions to the port 9000 but maintaining the HTTPS. The configuration in caddy for the site is:
mysite.com {
proxy / :9000 {
max_fails 1
}
log logfile
}
Nevertheless, it seems like when the proxy is made the HTTPS is lost. I checked the logs for the application (no the logs of caddy) and I get this:
http: TLS handshake error from xxx.xxx.xxx.xxx:xxxx: tls: oversized record received with length 21536
So, based in this error, to me looks like the HTTP proxy made by caddy is losing the HTTPS. What can I do?
From the caddy docs
to is the destination endpoint to proxy to. At least one is required,
but multiple may be specified. If a scheme (http/https) is not
specified, http is used. Unix sockets may also be used by prefixing
"unix:".
So maybe it is sending http requests to the proxied https endpoint.
Does
mysite.com {
proxy / https://localhost:9000 {
max_fails 1
}
log logfile
}
fix it?
If that is the case, you may not strictly need your app on :9000 to listen https. It may simplify your deployment or cert management to just have it listen http and have caddy manage all the certs.

How to configure nginx to make ssh server via subdomain.domain.tld:80 available

I want to make the ssh server on port 22 available through a subdomain on port 80.
I thought it should by something like this:
server {
listen ssh.domain.tld:80;
server_name ssh.domain.tld;
location / {
proxy_pass http://localhost:22;
}
}
But it won't work. nginx will accept this and start with this configuration, but I only get empty responses from ssh.domain.tld:80.
What am I missing?
Since Nginx Version 1.9.0,NGINX support ngx_stream_core_module module, it should be enabled with the --with-stream. When stream module is enable they are possible to ssh protocol tcp proxy
stream {
upstream ssh {
server localhost:22;
}
server {
listen 80;
proxy_pass ssh;
} }
https://www.nginx.com/resources/admin-guide/tcp-load-balancing/
You should use sslh.
Configure nginx to run on a different port than 80, say 800, and then configure sslh to redirect web traffic to that port in /etc/default/sslh.conf file.
This setup may take 15 min. or less.
basically you're looking in the wrong place:
stock nginx can proxy web and/or email traffic, it doesn't handle ssh traffic at all
the subdomain is a dns isue: configure it in your dns settings, you need an A and/or AAAA record linking ssh.domain.tld to your ssh server's ip-adres
the port your ssh server listens on is a ssh server setting (see man sshd_config specifically the ListenAddress and Port directives)