0

Vague title I know but I wasn't sure how to summarise what I am trying to achieve.

Basically, I have an internet router port forwarding port ext port TCP 443 to the same port on an internal IP addressed linux reverse proxy running apache 2.2.

This reverse proxy is then forwarding connections on to the actual hosts of the web content.

Previously the server doing the reverse proxying was the internet gateway, and this worked as it had the public IP address that the CNAME resolved to for the name based vhosting.

However, since now this server has an internal IP address this is broken.

How can I achieve this or is there a better way if I want to use CNAMEs for name based vhosting.

What I had tried and failed at was to use rewrite to rewrite the address to the internal hostname but since that changes the address for the client of course they can't hit it.

<VirtualHost blah.somedomain.net:443>
    ServerName blah.somedomain.net

    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^blah\.somedomain\.net$
    RewriteRule (.*) https://blah-proxy.somedomain.int
    <Location />
        Order deny,allow
        Allow from all
    </Location>
</VirtualHost>

<VirtualHost blah-proxy.somedomain.int:443>
    ServerName blah-proxy.somedomain.int
    ProxyPass / http://blah.somedomain.int/
    ProxyPassReverse / http://blah.somedomain.int/

    <Location />
        ProxyPassReverse /
        Order deny,allow
        Allow from all
    </Location>
    SSLEngine On
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/blah.somedomain.net/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/blah.somedomain.net/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/blah.somedomain.net/chain.pem
</VirtualHost>

Any suggestions?

Cheers

Andy


I tried the following instead, adding an IP address alias interface:

<VirtualHost 192.168.0.100:443>
    ServerName blah.somedomain.net
    ProxyPass / http://blah.somedomain.int/
    ProxyPassReverse / http://blah.somedomain.int/

    <Location />
        ProxyPassReverse /
        Order deny,allow
        Allow from all
    </Location>
    SSLEngine On
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/blah.somedomain.net/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/blah.somedomain.net/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/blah.somedomain.net/chain.pem
</VirtualHost>

I just don't get how a connection from an external source can get port forwarded to this webserver and the correct virtual host be identified and connections forwarded.

With the above it still changes the url to .int and fails.

  • 1
    If your URL was changed, that is your web application, not Apache. You have not configured a redirect in Apache. You also should not use domains which are not registered to you, such as subdomains of .int, which is a valid global top-level domain. – Michael Hampton Apr 18 at 5:52
2

Your virtual hosts never match because you used names in them, though this is documented as not recommended. Your current setup is one reason why.

Because you used a name, Apache must look up the name to find the IP address to listen on, for connections that match that virtual host. Since that machine no longer has a global IP address, the IP address from DNS will never match.

You should instead match on any address. There's occasionally a good reason to specify an IP address in <VirtualHost>, but there's virtually never a good reason to use a name. In this case there's no real reason to use either.

<VirtualHost *:443>
  • 0 thanks for responding. I'm not sure how you could implement that solution without getting: [warn] default VirtualHost overlap on port 443, the first has precedence I am running more than one virtualhost. They can't all be *:443 I could use IP based virtual hosting but it will still be an internal IP address. – anfieldroad Apr 18 at 3:56
  • @anfieldroad Huh? Did you actually receive that message? All of your virtual hosts can be on port 443 for any IP address. What version of Apache did you install? I think you didn't actually try this. You should do so first. – Michael Hampton Apr 18 at 4:01
  • Hi yes it was just a warning, all good on that front. The issue as commented on another answer is that it is changing the address to the .int internal non-routable address. I just want it to reverse proxy it. – anfieldroad Apr 18 at 10:15
0

You have more than one issue here.

  1. If your web server is behind a router and port forwarding is in place, you have the following scenario. Requests from internet come to you public IP of your router's internet connection. Router recognizes packets for internal site based on port forwarding rules, and replaces destination IP in all these packets. That means that it forwards that traffic to your internal server with internal IP. For your server nothing else as the packet's destination IP is changed on the way through router. Router also takes care that responds that it gets from internal web server are properly recognized and sent back to original sender as if they were sent from router. It masquerades (hides) your internal servers from internet. Therefore you should use internal IP in VirtualHost directives.

  2. Name based virtual hosts for HTTPS (SSL) was spedified in 2003 and available since 2007. The problem is that name based virtual hosting establishes a connection and then it sends the name of the site in HTTP request. Based on that HTTP request's name, web server knows which virtual site is being addresses. In HTTPS, certificates have to be exchanged to authenticate the site, so user can be sure she/he has come to the right place. To request site with a name in HTTPS request is far to late, because at that time the correct certificates have to be exchanged already. Therefore, SNI extension has been introduced, which allows name base virtual hosting. Take a look here https://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI and here http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslstrictsnivhostcheck. Since you have port forwarding, destination IPs are being replaced in order to come to your virtual host via router. That means that packets arriving to virtual host have internal destination IP, but the name of the site is not changed. So you should use internal IPs, and the correct (external) name of the web site for your virtual host configuration.

  3. You then have a reverse proxy to actual sites where the content is available. You have not specified if that content is in your internal network, or is it somewhere else. In fact, it does not really matter. You just need to make sure that the content is accessible from your reverse proxy with the addresses, which you specify in reverse proxy configuration. Try to setup internally accessible virtual hosts, where you can test your reverse proxies. You can do that by specifying names for internal IPs. Assign names for your web server's internal IP with hosts file (https://askubuntu.com/questions/183176/what-is-the-use-of-etc-hosts) on your client and web server. You can then use these names for internal name based virtual hosting, where you can test proxy and name based virtual hosts.

My advice would be to setup one site first, to see that everything works with port forwarding, reverse proxying, etc. Then add other sites. I have almost identical configuration of web server behind a firewall in DMZ using SNI and used as a reverse proxy for another site in internal network, and it works perfectly.

  • The thing I don't understand is how the webserver determines what virtual host to use. Externally the cname would be used but once it hits the port forward that gets lost as destination is the IP of the webserver. I don't really see what a solution should look like, are there any examples you can point me to? All my attempts so far result in a failed connection because it redirects the broser to the .int internal address which is supposed to be a reverse proxy. – anfieldroad Apr 18 at 9:53
  • Yes everything is on the internal network. Router port forwards to a linux server that is a firewall/gateway to my lab network. That server runs apache and does reverse proxying to the various web services in that lab. – anfieldroad Apr 18 at 10:25
  • When browser make a connection it also specifies the name of the site. In HTTP it adds another a line in HTTP header, which looks like this Host: blah.somedomain.net. In HTTPS it is a bit more complicated but still browser has to specify the hostname for apache to recognize the virtual host. – nobody Apr 19 at 10:40
  • I think you should use a virtualhost with internal IP and external hostname. Traffic to you apache comes via router, which replaces external IPs with internal ones. However the hostname remains the same. You should have everything in one virtualhost: internal IP, external hostname, and reverse proxy directives. You do not need rewrite rules, your site will be shown to external world as external site with external IP. Your router and apache will take care that content will be served from a computer hidden in your lab. Oh, I see now that you have done it already. Congratulations! – nobody Apr 19 at 10:45
0

After some tinkering and experimenting I have a working configuration:

<VirtualHost 192.168.20.250:443>
    ServerName blah.somedomain.net
    ProxyPass "/" "https://blah.somedomain.int/"
    ProxyPassReverse "/" "https://blah.somedomain.int/"

#    <Location />
#        ProxyPassReverse /
#        Order deny,allow
#        Allow from all
#    </Location>
    Loglevel debug
    ServerAdmin webmaster@somedomain.net
    ErrorLog logs/blah.somedomain.net-error_log
    CustomLog logs/blah.somedomain.net-access_log common
    SSLProxyEngine on
    SSLEngine On
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/blah.somedomain.net/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/blah.somedomain.net/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/blah.somedomain.net/chain.pem
</VirtualHost>

If this can be improved upon I am happy to hear suggestions but the main thing is it is functional right now :)

Thanks to all who responded.

Andy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.