Laravel routes behind reverse proxy - apache

Ok, so for development purposes, we have a dedicated web server. It's not currently connected directly to the internet, so I've setup an apache reverse proxy on another server, which forwards to the development server.
This way, I can get web access to the server.
The problem is, the routes in Laravel are now being prefixed with the internal server IP address, or the servers computer name.
For example, I go to http://subdomain.test.com but all the routes, generated using the route() helper, are displaying the following url: http://10.47.32.22 and not http://subdomain.test.com.
The reverse proxy is setup as such:
<VirtualHost *:80>
ServerName igateway.somedomain.com
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://10.47.32.22:80/
ProxyPassReverse / http://10.47.32.22:80/
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
I have set the actual domain name in config\app.php.
Question
How can I set the default URL to use in routing? I don't want it using the internal addresses, because that defeats the point of the reverse proxy.
I've tried enclosing all my routes in a Route::group(['domain' ... group, which doesn't work either.

I ran into the same (or similar problem), when a Laravel 5 application was not aware of being behind an SSL load-balancer.
I have the following design:
client talks to an SSL load balancer over HTTPS
SSL load balancer talks to a back-end server over HTTP
That, however, causes all the URLs in the HTML code to be generated with http:// schema.
The following is a quick'n'dirty workaround to make this work, including the schema (http vs. https):
Place the following code on top of app/Http/routes.php
In latest version of laravel, use web/routes.php
$proxy_url = getenv('PROXY_URL');
$proxy_schema = getenv('PROXY_SCHEMA');
if (!empty($proxy_url)) {
URL::forceRootUrl($proxy_url);
}
if (!empty($proxy_schema)) {
URL::forceSchema($proxy_schema);
}
then add the following line into .env file:
PROXY_URL = http://igateway.somedomain.com
If you also need to change schema in the generated HTML code from http:// to https://, just add the following line as well:
PROXY_SCHEMA = https
In latest version of laravel forceSchema method name has changed to forceScheme and the code above should look like this:
if (!empty($proxy_schema)) {
URL::forceScheme($proxy_schema);
}

Ok, so I got it. Hopefully this will help someone in the future.
It seems like Laravel ignores the url property in the config\app.php file for http requests (it does state it's only for artisan), and it instead uses either HTTP_HOST or SERVER_NAME provided by apache to generate the domain for URLs.
To override this default url, go to your routes.php file and use the following method:
URL::forceRootUrl('http://subdomain.newurl.com');
This will then force the URL generator to use the new url instead of the HTTP_HOST or SERVER_NAME value.

Go to app/Http/Middleware/TrustProxies.php and change the protected variable $proxies like this:
protected $proxies = ['127.0.0.1'];
Just this! Be happy!

Because laravel route is created not from the config/app itself rather than from the server. My solution is adding the proxy_set_header Host to the nginx's config.
server {
listen 80;
server_name my.domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host my.domain.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8000;
}
}
i'm using laravel 8 with nginx docker inside a running nginx on the machine, so yeah it's double nginx

add this code in App\Providers\AppServiceProvider class
if (Str::contains(Config::get('app.url'), 'https://')) {
URL::forceScheme('https');
}

Seems the Laravel have more convinient solution.. Check answer there: How do I configure SSL with Laravel 5 behind a load balancer (ssl_termination)?

Following up #TimeLord's solution:
In latest version of laravel the name for forced schema has changed and now it is:
URL::forceScheme()

I know this topic is old a.f but I've been solving this issue by replacing the following line in my DatabaseSessionHandler.pdf [#Illuminate/Session]:
protected function ipAddress()
{
return $_SERVER['HTTP_X_FORWARDED_FOR'];
// return $this->container->make('request')->ip();
}
Of course you need to migrate the sesssion table first and set up the config
(.env Variable SESSION_DRIVER=database)

For nginx, you don't need to do anything extra in Laravel. The fix can be done at from nginx config;
server {
listen 80;
listen [::]:80 ipv6only=on;
server_name sub.domain.dev;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host sub.domain.dev;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8000;
}
}

Figured out a way that much cleaner and only does exactly what the loadbalancer tells it to, add this function to your RouteServiceProvider
protected function enforceProtocol()
{
if(request()->server->has('HTTP_X_FORWARDED_PROTO')){
URL::forceScheme(request()->server()['HTTP_X_FORWARDED_PROTO']);
}
}
and in the boot section, simple call it like so
public function boot()
{
$this->enforceProtocol();
//other stuff
}

Related

ASK | Request URL was not found using nginx reverse proxy

First of all, I am so sorry if I broke any rules by making a thread / question.
And also I am sorry for my bad English.
I'm so stressed out to figure out the solution. I am learning about Reverse Proxy on Nginx.
So, I am making 2 servers (both are Centos), one using Apache Web Server and another using Nginx as Web Server. Both will run under an Nginx Reverse Proxy.
This is my configuration
server {
listen 80;
index index.html index.htm;
location / {
proxy_pass http://<apache-ip-address>;
}
location /demo {
proxy_pass http://<nginx-ip-address>;
}
}
And this seems working fine.
I can access the Apache Web Server using http://reverse-proxy-ip/ and access the Nginx Web Server using http://reverse-proxy-ip/demo
But, when I tried to change location / to nginx-ip-address , and /demo to apache-ip-address , I got error "Not Found. The requested URL /demo was not found on this server."
Here the configuration
server {
listen 80;
index index.html index.htm;
location / {
proxy_pass http://<nginx-ip-address>;
}
location /demo {
proxy_pass http://<apache-ip-address>;
}
}
So, my question is, why does this error occur after changing the destination server, and how to solve this problem?
Need some advice for a newbie like me.
Thank you.

Nginx - proxy_pass to google storage bucket static page VueJS sub paths cause 404 error, VueJS router not kicking in

I'm hosting VueJS at google cloud storage bucket, app works only when using domain name without subpath: www.domain.com when using URL like: www.domain.com/sub/path I'm getting 404 error as it seem that NGINX is looking for this path in the bucket instead of let VueJS router take over.
I tried to follow older thread but in my case would not help.
Any ideas how to fix this?
location = / {
proxy_pass https://gcs/mygoogle-cloud-bucket/main.html;
proxy_set_header Host storage.googleapis.com;
}
location / {
rewrite /(.*) /$1 break;
proxy_pass https://gcs/mygoogle-cloud-bucket/$1$is_args$args;
proxy_redirect off;
index main.html;
proxy_set_header Host storage.googleapis.com;
}
It seems like what you need to do is to create a Static Website using Cloud Storage and VueJS.
With this bieng the case, there are a few things that needs to be clarified:
Cloud Storage doesn't support HTTPs, so yo uneed to use a Load Balancer.
Make sure the objects in your bucket are public.
Build the Vue project With Relative Path.
It is also recomended to set the special pages, but this is not necessary.
Set up your load balancer and the SSL certificate as it is mentioned here.
Configure routing rules.
Make sure you have connected your custom domain to your load balancer
This should get you going with your site. If you would like to check a worknig example, you can take a look at this one.
Your code should look something like:
location / {
rewrite /$ $uri$index_name;
proxy_set_header Host storage.googleapis.com;
proxy_pass https://gs/$bucket_name$uri;
proxy_http_version 1.1;
proxy_set_header Connection "";
}

How to proxy custom domains to vuejs app?

I want to proxy multiple domains to my vuejs app.
I have a VueJS application, with the following route: https://app.pingr.io/status/{id}.
What I want to do is to allow users to redirect their domains to this route. So, imagine we have a https://status.some-domain.com host, which is redirected using CNAME to https://app.pingr.io/status/status.some-domain.com.
I really can't figure out the nginx configuration for this.
What I have right now:
server {
listen 80 default_server;
server_name _;
location / {
#resolver 127.0.0.1 [::1];
#resolver 8.8.8.8;
proxy_pass https://app.pingr.io/status/test/;
}
location /js/ {
proxy_pass https://app.pingr.io/js/;
proxy_ssl_server_name on;
proxy_set_header Accept-Encoding "";
}
location /css/ {
proxy_pass https://app.pingr.io/css/;
proxy_set_header Accept-Encoding "";
}
}
Before passing $host variable to proxy_pass at first I'm trying to just proxy to /status/test with working js/css/images.
I managed to get js/css work, however instead of getting the content of /status/test route, I get redirected to the home page. I displayed routes in router.beforeEach, so I can see that the first route I'm being redirected to is home route.
I was trying different configurations, like including proxy_set_header host and other stuff, which actually broke the whole thing even more.
So what is the right way to do this? Once again, users should be able to redirect their domains to my vuejs route and pass their domain to a part of this route. The domain should be rewritten, so that it looks like the page belongs to their server/domain.

Passing SSL traffic through corporate proxy using nginx

I have done some resarch for this matter and there are some unaswered question regarding my issue, however I managed to solve half of what is needed (thanks to people on the site).
Scenerio:
I have Nginx as a reverse proxy in internal corporate network. I need to pass traffic to Internet behind corporate proxy.
Half of the solution:
To achive this, following works fine:
server {
listen 80;
server_name myhost.com;
location / {
proxy_set_header Host google.com;
proxy_pass http://corporateproxy:9999/;
}
}
However, above solution does not use SSL between corporate proxy and google.com. Do you have any idea how to add SSL to this?
I have tried adding protocol or port to header but it is not working this way.
I cannot modify anything on the corporate proxy. It should work like this: the URL being accessed is with https it will be redirected to https; http to http. Unfortunatelly header that contains only dns name is treated as http request.
Unfortunatelly the simplest solution does not work because nginx does not respect http_proxy settings on RedHat Machine:
server {
listen 80;
server_name myhost.com;
location / {
proxy_pass https://google.com/;
}
}
Any help will be highly appreciated.

Is there a way to remove apaches Reverse Proxy Request Headers?

When acting as a reverse proxy, apache adds x-forwarded headers as described here.
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers
In my configuration I have configured server A as a forward proxy. There is a rule like this:
RewriteRule proxy:(.*example.com)/(.*) $1.mysecondserver.com/$2 [P]
This rule lets the server request the resource from one of my other servers.
On the second server (origin) I have a virtual host container for the resource and another rewrite rule like this:
RewriteRule some-regex some-url [P]
It may not seem to make sense like this but there is a lot of other stuff going on that I left out as it is not part of the problem.
However that final request has these headers:
[X-Forwarded-For] => ip of 1st server
[X-Forwarded-Host] => example.myseconserver.com
[X-Forwarded-Server] => example.com
I want those headers gone.
I seem to be unable to unset them with mod_headers. I can add more entries to them, but I can not remove them.
Any ideas?
Since Apache 2, as this pretty answer says, the
ProxyAddHeaders Off
theoretically disables it. In my experiences, it had no effect. However, combined with
<Proxy *>
ProxyAddHeaders Off
</Proxy>
and, with
RequestHeader unset X-Forwarded-Host
RequestHeader unset X-Forwarded-For
RequestHeader unset X-Forwarded-Server
somewhere it started to work.
corrected answer: there is no way to do that since its hardcoded
to fix this in the source code of mod_proxy_http.c search for the following part:
apr_table_mergen(r->headers_in, "X-Forwarded-Server",
r->server->server_hostname);
}
and immediately after that add this code:
// remove any X-Forwarded headers
apr_table_unset(r->headers_in, "X-Forwarded-For");
apr_table_unset(r->headers_in, "X-Forwarded-Host");
apr_table_unset(r->headers_in, "X-Forwarded-Server");
then compile by running apxs2 -cia mod_proxy_http.c
I had the same problem on httpd 2.2 on CentOS 5. Installing httpd 2.4 wasn't possible. But because of some reasons I couldn't switch to nginx completly. So I did it by inserting nginx proxy between httpd and the destination address. So I had: httpd(localhost:80/path) -> nginx(localhost:81/path) -> http://your.destination/path. Installation steps are the following:
Install nginx according to these instructions
Configure nginx to avoid security problems.
Add an location in nginx that will remove those httpd's reverse proxy request headers. It can look like this:
location /path {
proxy_set_header x-forwarded-for "";
proxy_set_header x-forwarded-host "";
proxy_set_header x-forwarded-server "";
proxy_pass http://your.destination/path;
}