Nginx reverse proxy DNS configuration - mysql

I am looking to deploy an nginx/dns server on a vps proxy that maps to the real back-end in a different geographical location. The back-end runs apache,mysql,dovecot,postfix. It is a pay-for mail server. The users get entered through apache through php into mysql, and when users set up IMAP, dovecot/postfix pools them from mysql and delivers or uses the smtp outbound.
I read about something in the nginx.conf file, that I can declare the mail hostname on the proxy as so:
mail {
server_name mail.example.com;
...
}
This mail.example.com is the actual mx for the example.com mail exchanger listed in DNS? Here is where that came from:
"As you can see, we declared the name of this server at the top of the mail context.
This is because we want each of our mail services to be addressed as mail.example.
com. Even if the actual hostname of the machine on which NGINX runs is different,
and each mail server has its own hostname, we want this proxy to be a single point
of reference for our users. This hostname will in turn be used wherever NGINX
needs to present its own name, for example, in the initial SMTP server greeting."
So from my understanding, the physical hostname of the proxy should be something else besides mail.example.com. So in DNS on the proxy, I can define that as anyhost.example.com? The proxy also proxies back to my apache on the back-end.
Finally, on the back-end, how do I set up my DNS for that? What hostname do I choose for the actual box running apache,mysql,dovecot,postfix? Its all on one box. I understand that on the registrar, I point 2 nameservers, these should be two proxies, that way running a dig would only pull up the proxies and the MX which should be "known" to be on the proxy.

in your case where all of the services in one box including the proxy, you can set the apache, mysql and other services accessible only from localhost / 127.0.0.1. Then from nginx you put
upstream: 127.0.0.1:80
upstream: 127.0.0.1:3306
therefore the nginx is serving frontend request and forward them to designated services

Related

Reverse proxy based on DNS for multiple mysql hosts

I've some mysql host in private network and would like to use a reverse proxy server (i.e. nginx) to connect with mysql-client to mysql host via reverse proxy server.
An example to better understand my answer:
suppose I've:
a mysql server with ip yyy.1
a mysql server with ip yyy.2
both in the network of a proxy server with ip XXX, and I associate to XXX the DNS mysql-server1.com and mysql-server2.com.
My goal is connect to mysql server yyy.1 when I use mysql client to connect to XXX by calling mysql-server1.com on port 3306, and similare when try mysql-server2.com on port 3306.
The problem with nginx is that I can't differenciate TCP request by server name, so in XXX server I should associate one port foreach mysql server, but this implies that every time I should change the port also in mysql client settings, and I don't wanna this!
There's some proxy-server that can accomplish that?
Could I use IP Table to route the request mysql-server1.com:3306 to localhost:[some port], where I could use [some port] in proxy setting to forward the requests to the server yyy.1?
This is impossible.
In the MySQL Client/Server protocol, the client never identifies the hostname to which it is attempting to connect to. Unlike in some other protocols, such as HTTP (with the Host header), the original name the client used to resolve an IP address from DNS is not preserved. TLS SNI is also not available, because TLS negotiation on a MySQL connection does not begin until the client reads the server capability flags to discover whether the server supports TLS, at which point the client asks to switch the connection to TLS... and this, of course, is after the connection is is already established.
In the MySQL Client/Server protocol, the server always talks first.
Your only options are for the proxy machine to listen on multiple IP addresses, with a DNS hostname pointing to each IP, and use the address to which the client connected to determine which server to use.
Or, each proxy instance listens on a separate port.
The protocol design prevents name-based virtual hosting.

How to make ELB pass protocol to node.js process (Elastic Beanstalk)

I have ELB balancing TCP traffic to my Node.js processes. When ELB is balancing TCP connections it does not send the X-Forwarded-Proto header like it does with http connections. But I still need to know if the connection is using SSL/TLS so I can respond with a redirect from my Node process if it is not a secure connection.
Is there a way to make ELB send this header when balancing TCP connections?
Thanks
You can configure proxy protocol for your ELB to get connection related information. In case of HTTP the ELB adds headers telling about the client information, in case of TCP however, AWS ELB simply passes through the headers from the client without any modifications, this causes the back end server to lose client connection information as it is happening in your case.
To enable proxy control for your ELB, you will have to do it via API, there is currently no way to do it via UI.
http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html
The above doc is a step-by-step guide on how to do this, I don't want to paste the same here as that information might change over time.
EDIT:
As it turns out, Amazon implements Version 1 of the proxy protocol only which does not give away SSL information. It does however give port numbers which was requested by the client and a process can be developed stating something like if the request was over port 443 then it was SSL. I don't like it as it is indirect, requires hardocoding and coordination between devops and developers... seems to be the only way for now...lets hope AWS ELB starts supporting Version 2 of the proxy protocol which does have SSL info soon.

Google Cloud HTTP Load Balancer can't connect to my instance

I have created a HTTP load balancer to basically redirect from port 80 to port 8080. The server on my instance is running on port 8080.
I can connect to the server directly but the LB is not able to connect to the instance, both accessing the LB's IP directly and also the health check always fails. The instance group the LB is using consist of just that single instance.
I read Google Compute Engine health checks failing
and the google-address-manager is running. However, when running ip route table list local there is no routing for my LB. The user in the above question is using Network load balancing and not HTTP load balancing (as I am) so I don't know if that is related?
Or perhaps it's related to a firewall? I have added my LB's ip address to a firewall rule that allows tcp:8080
Does anybode have any idea how can I fix this? I am not experienced with debian nor gcp.
Show I just try and run the route add command referenced in the above question? If so, how come the google-address-manager is not adding the route?
Thank you in advance!
You need to make sure that your port mapping on instance group is set to correct port, the 8080 in your case.
First, edit your instance group and change the port name and port to 8080:
Then, navigate to your http backend's settings and change the default port to the port name you've configured in your instance group.
Finally, make sure that your firewall rules allow access on port 8080 from 0.0.0.0/0 or at least from the IP address of HTTP load balancer (130.211.0.0/22)
I had the same issue and fixed it by adding a firewall rule for the health checker (which is not the same IP as your LB!). See https://cloud.google.com/compute/docs/load-balancing/health-checks?hl=en_US#http_and_https_load_balancing for instructions.
In my case, I did not configure the HTTP health check correctly.
I used "/" as path, but on my backend, "/" redirects to a login-page (HTTP 301), which responds with a HTTP 200.
The health check does not follow a redirect, every HTTP response code != 200 is assumed unhealthy (from Debugging Health Checks in Load Balancing on Google Compute Engine).
So, I changed my path to "/login", this fixed my issue.

create a domain name pointing to an IP of port different than 80

I would like to use a domain name to point to a web page on the local server's IP address. However, the problem is that the page is linked to an IP address set up on port 8088 rather than 80 because the latter is already used by another web page. By the domain company I was told that they cannot do it because the domain can only point to an IP address set up on port 80. So now I am in a deadlock. What alternatives do I have and how can I make a domain pointing to the IP:8088?
Thanks
The domain company that you talked to may have done a poor job of explaining how domains work. Domain names don't refer to specific ports. They just refer to IP addresses. The client can look up a hostname to get the IP address which the client should connect to, but the client has to figure out the port without the help of DNS. Port 80 is just the default port for HTTP service.
You can certainly run a web server on port 8088 if you like. The port number would have to appear in the URL, e.g. http://somehost.example.com:8080/some/page. Clients would parse this and know to connect to port 8080 instead of the default port 80.
If you don't want URLs to contain the port number, then requests are going to go to the default port 80, and you have no choice but to make the web server running on port 80 handle these requests. HTTP/1.1 requests include the hostname which the client wants to contact, and modern web server programs are normally capable of serving completely different sets of content based on the hostname in the request. There are few ways todo what you need:
Just configure the web server for port 80 to handle both sites. This will depend on what web server software you're using. Apache for example calls these "virtual hosts", and here is a set of examples. This is a typical solution, and some people run hundreds of sites on the same server this way.
Run your two web servers as you planned. Set up the server for port 80 to be a reverse proxy for the second website. The server would continue to serve content for the site it handles now. When it receives a request for the second site, it would relay the request to the server running on port 8088, and relay the server's response back to the client.
Move the existing server for port 80 to a different port. Run a pure reverse proxy server on port 80, relaying requests for both web sites to their respective web servers.
You might be better off taking further questions to https://webmasters.stackexchange.com/ or https://serverfault.com/.
You can use a Proxy to reroute the given domain to the IP:PORT. To accomplish this you could either spin up a Nginx server and configure it as your reverse proxy or use this project that does exactly what you want and with almost no config https://github.com/cristianoliveira/ergo
If you run Apache on port 80, which is the most common case then the easiest way to solve this issue is to set a VirtualHost that uses ProxyPass.
<VirtualHost sub.domain.com:80>
ProxyPass / https://ip-or-domain.com:8088/
</VirtualHost>

Qmail SMTP server behind firewall configuration

i've a problem with configuration Qmail + SimScan + SpamAssassin (dovecot + RoundCube) with SPF plugin.
For Spf spam prevention, this system rejects all mail that don't passed SPF test with tool "spfquery" (read SPF explanation for understand my problem).
My Network configuration is:
NAT/Firewall: 10.0.1.1
MailServer: 10.0.1.2
Dns Server : 10.0.1.19
External IP: 212.212.12.12
All modules in my mail server works greatly, also network configuration.
Now i've problem with SPF-rejection or DNSBL, beacuse server IP for incoming mail is 10.0.1.1
Log for smtp server is:
CHKUSER accepted sender: from remote mx5.pippo.com:unknown:10.0.1.1> rcpt <> : sender accepted
qmail-smtpd: spf-reject: HELO(mx5.pippo.com) from 10.0.1.1 MAILFROM:info#pippo.com
Why my tcpserver see mail from 10.0.1.1 and not from mx record of pippo.com?
This is a bad configuration of my NAT or tcpserver/smtp server?
Intersting question. I think something is wrong with your config.
If I understand correctly, your MX record for your domain points to 212.212.12.12, which is the external IP of your router. You have port-forwarding setup on your router, to forward incoming connections on 212.212.12.12:25 to 10.0.1.2:25, which is the IP of your mail server on your private network.
If that's the case, your mail server should still see the connections from the remote IP that they are originating from, it should not look like the connections are coming from 10.0.1.1. Port-forwarding only re-writes the destination IP address on the packets, not the source address.
To confirm this, I did a test on a similar setup that I have at my house. I logged in remotely to a Linux box that I have running on my home network, on an inside IP behind by router, like you have. The Linux box did indeed see that I was coming from my remote IP address, not my home router's IP address.