Meteor on httpd (Apache/2.4.6 CentOS) proxy and WebSockets - apache

I can't workout how to get WebSockets to work when I deploy my meteor app online. I keep getting this error:
WebSocket connection to 'ws://website.com/sockjs/***/********/websocket' failed: Unexpected response code: 400
I think this is due to the fact that apache sits in front of my meteor app. I know Apache 2.4 had a bug to make ws:// working, but I think this should be resolved by modules/mod_proxy_wstunnel.so, which I have enabled (of course I have enabled also modules/mod_proxy.so)
Here's my config. I'm running Meteor 1.2.1 as a systemd service (/etc/systemd/system/meteor.service) like so:
[Unit]
Description=meteor nodejs daemon
After=network.target remote-fs.target
[Service]
User=root
ExecStart=/usr/bin/node /home/root/www/main.js
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=meteor
Environment=ROOT_URL=http://website.com
Environment=PORT=3000
Environment=NODE_ENV=production
Environment=MONGO_URL=mongodb://127.0.0.1:27017/meteor
[Install]
WantedBy=multi-user.target
This is the output of httpd -v
Server version: Apache/2.4.6 (CentOS)
Server built: Aug 28 2015 22:11:18
And this is the relevant part in my vhost config (/etc/httpd/conf/httpd.conf) for website.com:
<VirtualHost my.ser.ver.ip:8080>
ServerName website.com
ServerAlias www.website.com
ProxyRequests Off
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
<Proxy *>
Allow from all
</Proxy>
</VirtualHost>
I've already tried to add the RewriteCond as suggested here but no success...
Any idea? I'm also having issue getting oauth to work with the accounts-facebook package and I guess the problem is for the same reason? As in, there is something wrong in my proxy settings?

Solved the mystery. Of course it was my bad: I forgot all about Varnish.
I had Varnish set on port 80 forwarding the request to Apache, which was in turn proxying the request to node.js. I resolved by removing apache and thus configuring Varnish to serve straight to node.js for that specific domain.
This is what I did:
Implemented this default.vcl in /etc/varnish/
Removed import directors and all the content inside sub vcl_init {} (as I only have a single server)
Replaced set req.backend_hint = vdir.backend(); in sub vcl_recv {} with:
if (req.http.Host ~ "^(www\.)?website.com") {
set req.backend_hint = nodejs;
} else {
set req.backend_hint = apache;
}
Created the two backends like so:
backend apache {
.host = "127.0.0.1";
.port = "8080";
.max_connections = 300;
.probe = {
.request =
"HEAD / HTTP/1.1"
"Host: localhost"
"Connection: close";
.interval = 5s;
.timeout = 1s;
.window = 5;
.threshold = 3;
}
.first_byte_timeout = 300s;
.connect_timeout = 5s;
.between_bytes_timeout = 2s;
}
backend nodejs {
.host = "127.0.0.1";
.port = "3000";
.connect_timeout = 1s;
.first_byte_timeout = 2s;
.between_bytes_timeout = 60s;
.max_connections = 800;
}

Related

307 Temporary Redirect On Specific Routes

I have an api service that i wrote with FastApi and served with gunicorn. Apache is working on the server as reverse proxy and ssl manage.
Everything was fine until i decided to use SqlAdmin as admin panel.
The problem is that my api endpoints works fine with SSL but SqlAdmin endpoints are not.
e.g: Responses i get when i want reach https://example.com/admin: (FAIL)
--- I summarized responses ---
307 Temporary Redirect -> http://example.com/admin
302 Not Found
Somehow redirect -> https://example.comadmin/
e.g: Responses i get when i want reach https://example.com/users: (PASS) (API ENDPOINT)
Request URL: https://example.com/users/
Request Method: GET
Status Code: 200 OK
Apache Configuration:
<VirtualHost ip:80>
ServerName subdomain.example.com
ServerAlias www.subdomain.example.com
ServerAdmin ****#gmail.com
Redirect / https://subdomain.example.com
</VirtualHost>
<VirtualHost ip:443>
ServerName subdomain.example.com
ServerAlias www.subdomain.example.com
ServerAdmin ******#gmail.com
ProxyRequests On
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
SSLEngine on
SSLCertificateFile *****
ProxyPass / http://example.com:8000/
ProxyPassReverse / http://example.com:8000/
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
Gunicorn Configuration:
import json
import multiprocessing
import os
workers_per_core_str = os.getenv("WORKERS_PER_CORE", "1")
max_workers_str = os.getenv("MAX_WORKERS")
use_max_workers = None
if max_workers_str:
use_max_workers = int(max_workers_str)
web_concurrency_str = os.getenv("WEB_CONCURRENCY", None)
host = os.getenv("HOST", "0.0.0.0")
port = os.getenv("PORT", "80")
bind_env = os.getenv("BIND", None)
use_loglevel = os.getenv("LOG_LEVEL", "warning")
if bind_env:
use_bind = bind_env
else:
use_bind = f"{host}:{port}"
cores = multiprocessing.cpu_count()
workers_per_core = float(workers_per_core_str)
default_web_concurrency = workers_per_core * cores
if web_concurrency_str:
web_concurrency = int(web_concurrency_str)
assert web_concurrency > 0
else:
web_concurrency = max(int(default_web_concurrency), 2)
if use_max_workers:
web_concurrency = min(web_concurrency, use_max_workers)
accesslog_var = os.getenv("ACCESS_LOG", "/var/log/gunicorn/access_log")
use_accesslog = accesslog_var or "/var/log/gunicorn/access_log"
errorlog_var = os.getenv("ERROR_LOG", "/var/log/gunicorn/error_log")
use_errorlog = errorlog_var or "/var/log/gunicorn/error_log"
graceful_timeout_str = os.getenv("GRACEFUL_TIMEOUT", "120")
timeout_str = os.getenv("TIMEOUT", "120")
keepalive_str = os.getenv("KEEP_ALIVE", "5")
# Gunicorn config variables
loglevel = use_loglevel
workers = web_concurrency
bind = use_bind
errorlog = use_errorlog
worker_tmp_dir = "/dev/shm"
accesslog = use_accesslog
graceful_timeout = int(graceful_timeout_str)
timeout = int(timeout_str)
keepalive = int(keepalive_str)
# For debugging and testing
log_data = {
"loglevel": loglevel,
"workers": workers,
"bind": bind,
"graceful_timeout": graceful_timeout,
"timeout": timeout,
"keepalive": keepalive,
"errorlog": errorlog,
"accesslog": accesslog,
# Additional, non-gunicorn variables
"workers_per_core": workers_per_core,
"use_max_workers": use_max_workers,
"host": host,
"port": port,
}
print(json.dumps(log_data))
I dont have any idea how this behavior happend at all so any clue would be helpful :)
Thanks in advance.
I did try to add middleware to the FastApi. HTTPSRedirectMiddleware.
every requests reached to this response on gunicorn:
WARNING: Invalid HTTP request received.
I did try to start gunicorn with --forwarded-allow-ips='*' and --proxy-headers.
Nothing changed.

How to setup Varnish to work with Apache and Tomcat

I have a Ubuntu 12.0 server running Varnish 4 on port 80 and the Apache 2.4 in 8080.
I installed Tomcat 7 running on port 8181, which runs only one Liferay site.
I would like to configure Varnish to work with Tomcat also.
How do I set this up?
My current setup is this:
/etc/default/varnish
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
/etc/varnish/default.vcl
backend default {
.host = "123.456.789.000";
.port = "8080";
.connect_timeout = 580s;
.first_byte_timeout = 580s;
.between_bytes_timeout = 580s;
}
If I point my browser to 123.456.789.000:8181 the Tomcat site works. I will set the registar with my DNS to respond to "www.mytomcatsite.com", but how can I avoid the ":8181" on the URL ?
With Apache everything works fine.
TIA.
From the varnish documentation:
We add a new backend.:
backend java {
.host = "127.0.0.1";
.port = "8000";
}
Now we need tell Varnish where to send the difference URL. Lets look at vcl_recv.:
sub vcl_recv {
if (req.url ~ "^/java/") {
set req.backend_hint = java;
} else {
set req.backend_hint = default;
}
}
If you want this routing to be done on the basis of virtual hosts you just need to inspect req.http.host:
sub vcl_recv {
if (req.http.host ~ "foo.com") {
set req.backend_hint = foo;
} elsif (req.http.host ~ "bar.com") {
set req.backend_hint = bar;
}
}
See:
https://www.varnish-cache.org/docs/trunk/users-guide/vcl-backends.html#multiple-backends
https://www.varnish-cache.org/docs/trunk/users-guide/vcl-backends.html#backends-and-virtual-hosts-in-varnish
Note: This is for Varnish 4. The VCL syntax will be slightly different for Varnish 3.

Why is Varnish redirecting as 301?

I have been deploying a mediawiki docker container (appscontainer/mediawiki) based on Apache2 on a VPS, and I put a fresh install of Varnish on top of it, to be able to proxied different subdomains to the proper applications on the same server.
My current default.vcl configuration file look like the following:
backend default {
.host = "127.0.0.1";
.port = "8080";
}
backend wikimedia {
.host = "localhost";
.port = "8080";
}
sub vcl_recv {
if(req.http.host == "wiki.virtual-assembly.org") {
set req.backend_hint = wikimedia;
}
set req.backend_hint = default;
}
My issue is that when I request the URL http://wiki.virtual-assembly.org, I got redirected via a 301 to the IP adress of the server on port 8080 (port on which the apache2 instance is listening).
Is there a way to tell Varnish to keep the location to be http://wiki.virtual-assembly.org, or is it an apache2 misconfiguration ?
Thanks in advance,
PS: I know my two backends are equivalent, I will change the default in the future when I will have deployed more apps.
Shot in the dark answer. Do you still get a 301 if you put the default backend_req into an else statement instead of outside the if?

Varnish on cPanel server req.http.X-Forwarded-For not working

I have installed Varnish (uses 4.0 vcl format) and i did like here: http://wiki.mikejung.biz/How_To_Forward_IP_Header_Varnish_Apache
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
in vcl file and
<IfModule mod_remoteip.c>
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1
</IfModule>
in cPanel include editor. But i am still see only server IP in logs. This is very important because csf and mod_security cant block briteforce attacks on server. Varnish itself running ok.
This worked for me:
Varnish 4 doesn't require any changes in vcl config file
Include mod_remoteip module in Apache configuration
Add to /usr/local/apache/conf/mod_remoteip.conf
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1 ...
Replace in lines including logformat: '%h' with '%a' in /var/cpanel/conf/apache/main
5.
/scripts/rebuildhttpdconf
/sbin/service httpd graceful

varnish 3 and multiple IPs (virtualhosts) isn't working out too well for me

Complete newbie to Varnish so apologies ahead of time if this seems rather silly.
Here's the situation. I have a server with 5 IPs. Using ISPconfig for most tasks but that's probably irrelevant.
I have multiple apache virtual hosts configured across multiple IPs.
The issue is that varnish is putting out a 503, fetch error no backend connection (according to varnishlog) on any of the non-default virtual hosts i.e. ones with a static IP defined in vhosts. Any *:8080 vhosts are working ok. So I'm missing something somewhere. All of the vhost error logs show file does not exist errors though the path looks correct.
Suggestions are much appreciated.
I have of course manually edited all vhost entries and configured them accordingly i.e.
<VirtualHost 00.11.22.33:8080>
DocumentRoot /var/www/shop.example1.com/web
Here's my vcl config
backend default {
.host = "127.0.0.1";
.port = "8080";
}
backend example1 {
.host = "00.11.22.33";
.port = "8080";
}
backend example2 {
.host = "11.22.33.44";
.port = "8080";
}
acl purge {
"localhost";
}
sub vcl_recv {
if (req.http.host ~ "(?i)^(www.)?example1.com")
{
set req.http.host = "www.example1.com";
set req.backend = example1;
}
if (req.http.Host ~ "shop\.example2\.com")
{
set req.http.Host = "shop.example2.com";
set req.backend = example2;
}
set req.grace = 2m;
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
if (req.url ~ "/wp-(login|admin|cron)") {
return (pass);
}
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");
if (req.url ~ "wp-content/themes/" && req.url ~ "\.(css|js|png|gif|jp(e)?g)") {
.......
'
Damn obvious thing of course.
port.conf had:
NameVirtualHost *:8080
Listen 127.0.0.1:8080
What it needed was:
NameVirtualHost *:8080
Listen 127.0.0.1:8080
Listen my_IP1:8080
Listen my_IP2:8080