Block HTTP_X_FORWADED_FOR by iptables - nginx

I have to 2 servers:
- front
- backend
Front server is a proxy to backend
I have no access to front server.
So..
How i can block ip address in backend, if i see real ip only in http_x_forwaded_for header?

I think you can not.
You can:
block the IP on front server - this is the way you must do it.
also is probably good idea to firewall backend server from all IP addresses but front server and probably your administrative IP's.
use webserver on backend to block based on the header.
on Apache this can be done with .htaccess.
on backend, use the scripting language (PHP or whatever) to show blank page based on the header.

Related

Map DNS entry to specific port

Let's say I have this DNS entry: mysite.sample. I am developing, and have a copy of my website running locally in http://localhost:8080. I want this website to be reachable using the (fake) DNS: http://mysite.sample, without being forced to remember in what port this site is running. I can setup /etc/hosts and nginx to do proxing for that, but ... Is there an easier way?
Can I somehow setup a simple DNS entry using /etc/hosts and/or dnsmasq where also a non-standard port (something different than :80/:443) is specified? Without the need to provide extra configuration for nginx?
Or phrased in a simpler way: Is it possible to provide port mappings for dns entries in /etc/hosts or dnsmasq?
DNS has nothing to do with the TCP port. DNS is there to resolv names (e.g. mysite.sample) into IP addresses - kind of like a phone book.
So it's a clear "NO". However, there's another solution and I try to explain it.
When you enter http://mysite.sample:8080 in your browser URL bar, your client (e.g. browser) will first try to resolve mysite.sample (via OS calls) to an IP address. This is where DNS kicks in, as DNS is your name resolver. If that happened, the job of DNS is finished and the browser continues.
This is where the "magic" in HTTP happens. The browser is connecting to the resolved IP address and the desired port (by default 80 for http and 443 for https), is waiting for the connection to be accepted and is then sending the following headers:
GET <resource> HTTP/1.1
Host: mysite.sample:8080
Now the server reads those headers and acts accordingly. Most modern web servers have something called "virtual hosts" (i.e. Apache) or "sites" (i.e. nginx). You can configure multiple vhosts/sites - one for each domain. The web server will then provide the site matching the requested host (which is retreived by the browser from the URL bar and passed to the server via Host HTTP header). This is pure HTTP and has nothing to do with TCP.
If you can't change the port of your origin service (in your case 8080), you might want to setup a new web server in front of your service. This is also called reverse proxy. I recommend reading the NGINX Reverse Proxy docs, but you can also use Apache or any other modern web server.
For nginx, just setup a new site and redirect it to your service:
location mysite.example {
proxy_pass http://127.0.0.1:8080;
}
There is a mechanism in DNS for discovering the ports that a service uses, it is called the Service Record (SRV) which has the form
_service._proto.name. TTL class SRV priority weight port target.
However, to make use of this record you would need to have an application that referenced that record prior to making the call. As Dominique has said, this is not the way HTTP works.
I have written a previous answer that explains some of the background to this, and why HTTP isn't in the standard. (the article discusses WS, but the underlying discussion suggested adding this to the HTTP protocol directly)
Edited to add -
There was actually a draft IETF document exploring an official way to do this, but it never made it past draft stage.
This document specifies a new URI scheme called http+srv which uses a DNS SRV lookup to locate a HTTP server.
There is an specific SO answer here which points to an interesting post here

Can nginx support URL based server blocks (VirtualHosts)?

Note: “VirtualHost” is an Apache term. NGINX does not have Virtual hosts, it has “Server Blocks”. (https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/).
I know about ip-based and name-based server blocks, but is it possible to have URL-based server blocks? In other words, I want http://example.com/foo and http://example.com/bar to be served from completely independent roots. This would be a trivial problem to solve with name-based server blocks if the names were different http://example1.com and http://example2.com, but since the names are the same (example.com) and only the path part of the URL is different... Can nginx support separate server blocks for these types of URL's?
See https://nginx.org/en/docs/http/request_processing.html
It seems the only options available are: IP address, port, host, and if none of those match, then it serves the default server. So, given that the name and port are the same in both cases, the only possible solution is to put a proxy server in front of nginx, and have the proxy server distribute to the backend nginx server using a different IP or port.

Faking an HTTP request header

I have a general networking question but it's related with security aspect.
Here is my case: I have a host which is infected by a malware. The malware creates an http packet to communicate with it's command and control server. While constructing the packet, the IP layer contains the correct IP address of the command and control server. The tcp layer contains the correct port number 80.
Before sending the packet out, the malware modifies the http header to replace the host header with “google.com" instead of it's server address. It then attaches the stolen data with the packet and sends it out.
My understanding is that the packet will get delivered to the correct server because the routing will happen based on the IP.
But can I host a webserver on this IP that would receive all packets with header host google.com and parse it correctly?
Based on my reading on the internet, it is possible but if it is that easy then why have malware authors not adopted this technique to spoof the http headers and bypass traditional domain whitelisting engines.
When you make a request to let's say Apache2 server, what actually Apache does is match your "Host" header with any VirtualHost within server's configuration. Only if it cannot be found / is invalid, Apache will route the request to default virtualhost if it's defined. Basically nothing stops you from changing these headers.
You can simply test it by editing your hosts file and pointing google.com to any other IP - you will be able to handle the google.com domain on your server, but only you will be to use it this way - no one else.
Anything you send inside HTTP headers shouldn't be trusted - it just a guide for your server on how to actually handle the traffic.
The fake host header is just there to trick some deep-inspection firewalls ("it's for Google? you may pass..."). The server on that IP either doesn't care about the host header (default vhost) or is explicitly configured to accept it.
Passing the loot on by using fake headers or just as plain data behind the headers is another trick to fool data loss prevention.
These methods can mislead shallow application-layer inspection but won't pass a decent firewall.

facing an issue with haproxy / nginx

I need to setup a reverse proxy server which would distribute traffic to the backend servers based on the incoming HOST header.
I opted for HAproxy for this but after setting up everything I realized that HAproxy reads the configuration just once when the service starts and continues to use the backend IP address unless it has been reloaded/restarted.
This is an issue for me since in my case if the backend server reboots it will have a different IP address and I dont have control on which IP address it gets.
I am thinking of moving to nginx server but before I go through all the setup I would like to know if we have the same issue with Nginx or not?
Meaning: If in the configuration file I have specific the name of backend server and if the related IP address changes, will Nginx refresh its dns cache to identify the new IP address?
(When the backend server changes IP, it is automatically updated in the hosts file of proxy server)
Yes, nginx will do the job. See 'resolve' option here:
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server

Avoiding framed forwarding for web app on port 8080 with DNS

I have a play application running on port 8080. I currently forward to this by using
http://ip_address:8080
as my 'URL to forward to' in my forwarding service control panel.
The problem with this is: frame forwarding is used and I think this may be stopping Google Analytic for working.
I have control over DNS
A, CNAME, AAAA, TXT and NS records
&
DNS Service records
For other websites in the past running on port 80 I have simply created an A record with the destination as the server IP address, however because I am using port 8080 in this case, this does not work.
What is the best way to go about getting away from framed forwarding?
You can't put port numbers into the DNS resource record (there's a notable exception, namely SRV records, but as client support for those is rather spotty, those won't be much help). A nameserver commonly resolves hostnames to ip addresses - no directory/file names, no port numbers.
You can use a permanent redirect, which is a webserver facility, used to tell web clients to contact a different webhost. In order to use that, you need a webserver which responds to requests on port 80, and knows that requests concerning your zone must be redirected to your actual webserver. Very similar to the iframe solution you've been already using, but a permanent redirect instead of iframe.
If your reason for dropping the current iframe approach isn't that you, for example, want to get rid of decorative framing, ads, "branding" etc (with those, a permanent redirect would help), but want to cease using an intermediate webserver, adding another level of indirection to the queries, there's little you can do:
your firewall may be able to do port redirection, meaning that the incoming requests will hit your gateway/firewall on port 80, where the request is sent on to port 8080 where the webserver is actually listening. Another possibility could be, but requiring again another webserver, listening to port 80, to set up proxying: incoming requests to that webserver will be served from a cache on that server, which is populated and occasionally refreshed as result of that webserver querying your webserver on port 8080.
Even though with the latter suggestion an additional webserver will be existing, there'd be no visible indirection, as it would be transparent to clients: The web files are produced by the first server which is hit, even if they are once every so often taken from another server.

Resources