HAproxy with standalone mod_security routed to multiple web servers - apache

I want to have one server with HAproxy and a standalone mod_security installed which routes every packets to mod_security first and check by its rules.
Then if there wasn't anything suspicious in packets (SQL Injection, DOS Attacks, ...) pass them back from mod_security to haproxy and haproxy routes them to multiple servers with different webservers.
Therefore I don't need to install and config mod_security on all my webservers.

This is technically possible, possibly with running 2 instances of HAProxy. However, you will need a webserver to run underneath ModSec, typically Apache or nginx, and this kind of negates the advantage of not having to install ModSec on all your webservers.
The standard setup is: haproxy -> reverse-proxies with ModSec -> application-servers

Just to answer this old, but still valid, question:
The solution should be to use HAProxies Stream Processing Offload Engine (SPOE) through the Stream Processing Offload Protocol (SPOP) to talk a Stream Processing Offload Agent (SPOA) which is a standalone modsecurity daemon.
HAProxy example config from their github repo
frontend my-front
...
filter spoe engine modsecurity config spoe-modsecurity.conf
...
enter code here
backend spoe-modsecurity
mode tcp
balance roundrobin
timeout connect 5s
timeout server 3m
server modsec1 127.0.0.1:12345
# Block potential malicious requests with returncode < 0
http-request deny if { var(txn.modsec.code) -m int gt 0 }
There's also a Github project where the daemon has been made available as Docker container
Offical HAProxy blog post

Related

Clustering doesn't work with mod_cluster on JbossAS7 - Stateful Application

I'm going to explain my situation.
Background:
I'm running three virtual machines with Debian Jessie on Open Nebula, one as master and the other two as slaves. In them i've installed JBoss AS 7.1 and mod_cluster 1.2.
Goal:
Run a stateful app, so when I shutdown the master server the cluster allows me to continue using the app with shared session and mantain the variables values.
I followed this guide with the given web application.
Errors:
I can't access directly the app at http://master/cluster-demo/ like as in the guide above, I have to specify the port (8330 for server-three).
When I shutdown server-three the slaves notices that the server is shutted down but the session is not shared and the application is no more accessible. This is the output on slave when i shoutdown server-three on master.
Configuration Files
I attach my configuration files:
/opt/jboss/domain/configuration/domain.xml
/opt/jboss/httpd/httpd/conf/httpd.conf
/opt/jboss/domain/configuration/host.xml in the master
/opt/jboss/domain/configuration/host.xml in the slaves
Answer
mod_cluster does not have anything in common with messaging (JMS, HornetQ) subsystems. mod_cluster setting also does not have anything in common with clustering subsystem, i.e. Infinispan and its workhorse, JGroups.
What AS7 mod_cluster subsystem does is that is listens to UDP multicast advertising messages emitted by Apache HTTP Server mod_cluster modules. When it receives such message, it registers itself with your Apache HTTP Server load balancer. From that moment, your registered AS7 "worker" node keeps sending specialized HTTP messages (via TCP), informing Apache HTTP Server about:
its name (jvmRoute or generated)
its current load
its deployments, i.e. application contexts
aliases etc.
When there are no worker nodes registered with your Apache HTTP Server balancer, there are no contexts, hence there is nowhere to forward your requests to.
According to the configuration you posted, you rely on UDP multicast messages being sent to/received from 224.0.1.105:23364.
Open Nebula, firewall and UDP multicast
It is possible that Open Nebula doesn't allow UDP multicast between hosts or that your iptables are blocking it. Try this:
use curl on your worker host to access the balancer host -- exactly the VirtualHost where you have the directive EnableMCPMReceive defined.
if it doesn't work, you must fix iptables, selinux, httpd's allow/deny and such
if it works, it's a good sign that worker can talk to the balancer
go to your AS7 xml, modcluster subsystem, and add attribute to the config: <mod-cluster-config advertise-socket="modcluster" proxy-list="your-httpd-address:port"> -- the one you've just tried with curl
now it should work even without UDP multicast
if you would like to debug your UDP multicast settings in Open Nebula, give it a shot with Advertize.java
1.2.0 is too old, do not use vulnerable code
Please, do not use mod_cluster 1.2.0 with your Apache HTTP Server. The version is completely obsolete and it contains serious bugs, including a code injection CVE and severe performance issue. Download mod_cluster 1.3.1.Final for httpd 2.4.x or build your own from the sources, if you desire httpd 2.2.x support. If you happen to need any any help with that, ask.

SailsJS on production - Error: listen EADDRINUSE

I have a VPS server with CentOS and Apache server.
But I want to run my node.js applications too. I am using sails.js
This sails application is trying to listen to port 80 of specified host.
Here is error (after sails lift running):
debug: Starting server in /var/www/user/data/nodeprojects/projectname...
info - socket.io started
debug: Restricting access to host: projectname.com
warn - error raised: Error: listen EADDRINUSE
warn:
warn: Server doesn't seem to be starting.
warn: Perhaps something else is already running on port 80 with hostname projectname.com?
What is the problem? Can I run both apache and nodejs servers on one server with one port (80)?
No, you cannot.
When a server process opens a TCP port to answer requests, it has exclusive use of that port. So, you cannot run both SailsJS and Apache servers on the same port.
Having said that, you can do lots of interesting things with Apache, such as proxying specific requests to other servers running on different ports.
A typical setup would have Apache on port 80 and SailsJS on port 8000 (or some other available port) where Apache would forward requests to certain URLs to SailsJS and then forward the reply from SailsJS back to the browser.
See either configuring Apache on Mountain Lion proxying to Node.js or http://thatextramile.be/blog/2012/01/hosting-a-node-js-site-through-apache for example implementations of this approach.
you cannot use same port for different application. NodeJS can use any open port. What you need todo is port forwarding for your app. :)

Deploy pyramid app with uwsgi and apache

I have a pyramid app in a virtualenv, and I want to deploy it using apache+uwsgi, but I don't figure how to connect apache, uwsgi and pyramid. Can anyone provide an apache.conf and production.ini example?
In many examples you should create an init script to manage the uWSGI process, but can apache start the uwsgi process?
I can't help with the Apache side of things, but here's my uwsgi config.ini that would work in your case. Apache does not support the native uwsgi protocol, so you will need to configure uwsgi to speak http as below. Then, Apache will need to be configured to proxy requests to a backend http server.
http = 127.0.0.1:33932 ;also could use unix file socket
master = 1
workers = 5 ;number of cpus + 1
harakiri = 30 ;seconds = request timeout length
buffer-size = 32768 ; found experimentally. Your app may work well with less or more.
chdir = /path/to/your/uwsgi_webapp
module = your_module
callable = your_wsgi_app
virtualenv = /path/to/your/uwsgi_webapp/env
daemonize = /path/to/your/uwsgi_webapp/log/uwsgi.log
pidfile = /path/to/your/uwsgi_webapp/uwsgi_fuzzy.pid
Note that using Apache as a front-end webserver is not a recommended configuration. Starting up a complete Apache process just to proxy to another http server will result in fairly poor performance. For that reason, a lightweight server like nginx or a http proxy like Varnish is preferred.

Python twisted proxyclient cascade / upstream to squid

I would like to run a small http proxy server on my machine which sends all requests to an upstream / cascading proxy server.
Twisted Web HTTP Proxy -> Squid -> Internet connection
Unfortunately I cannot figure out how to send all ProxyClient requests upstream / cascade them to Squid. Could you give me a hint?
Do I have to use reactor.connectTCP and HttpClientFactory for this and somehow direct the Squid response through?
I have used the following Twisted code sample to get the twisted http proxy up:
from twisted.web import proxy, http
from twisted.internet import reactor
from twisted.python import log
import sys
log.startLogging(sys.stdout)
class ProxyFactory(http.HTTPFactory):
protocol = proxy.Proxy
reactor.listenTCP(8080, ProxyFactory())
reactor.run()
Thanks,
Mathias
I think you're over complicating things. To me, it sounds like what you want to do is round-robin load balance http proxy requests between two squid services.
If it was me, I wouldn't write a byte of code and use something off the shelf.
I'd use HA-Proxy with a configuration something like this:
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend loadbal
bind *:3128
default_backend squids
option http_proxy
backend squids
option http_proxy
server squid1 192.168.1.2:3128
server squid2 192.168.1.3:3128
balance roundrobin
You might need to do some playing around, some webservices may require certain types of stickiness, but this application is highly configurable in this regard. It looks like HA-Proxy v 1.4 supports keep alive connections, which may simplify some of the corner cases I can imagine.
Oh, also, if you're trying to get the most out of your two connections, I'd suggest that you configure ICP between your two squid boxes.
This sounds like something twisted.web.proxy.ReverseProxyResource might be good for.

Tunnel over HTTPS

At my workplace, the traffic blocker/firewall has been getting progressively worse. I can't connect to my home machine on port 22, and lack of ssh access makes me sad. I was previously able to use SSH by moving it to port 5050, but I think some recent filters now treat this traffic as IM and redirect it through another proxy, maybe. That's my best guess; in any case, my ssh connections now terminate before I get to log in.
These days I've been using Ajaxterm over HTTPS, as port 443 is still unmolested, but this is far from ideal. (Sucky terminal emulation, lack of port forwarding, my browser leaks memory at an amazing rate...) I tried setting up mod_proxy_connect on top of mod_ssl, with the idea that I could send a CONNECT localhost:22 HTTP/1.1 request through HTTPS, and then I'd be all set. Sadly, this seems to not work; the HTTPS connection works, up until I finish sending my request; then SSL craps out. It appears as though mod_proxy_connect takes over the whole connection instead of continuing to pipe through mod_ssl, confusing the heck out of the HTTPS client.
Is there a way to get this to work? I don't want to do this over plain HTTP, for several reasons:
Leaving a big fat open proxy like that just stinks
A big fat open proxy is not good over HTTPS either, but with authentication required it feels fine to me
HTTP goes through a proxy -- I'm not too concerned about my traffic being sniffed, as it's ssh that'll be going "plaintext" through the tunnel -- but it's a lot more likely to be mangled than HTTPS, which fundamentally cannot be proxied
Requirements:
Must work over port 443, without disturbing other HTTPS traffic (i.e. I can't just put the ssh server on port 443, because I would no longer be able to serve pages over HTTPS)
I have or can write a simple port forwarder client that runs under Windows (or Cygwin)
Edit
DAG: Tunnelling SSH over HTTP(S) has been pointed out to me, but it doesn't help: at the end of the article, they mention Bug 29744 - CONNECT does not work over existing SSL connection preventing tunnelling over HTTPS, exactly the problem I was running into. At this point, I am probably looking at some CGI script, but I don't want to list that as a requirement if there's better solutions available.
Find out why the company has such a restrictive policy. It might be for a good reason.
If you still find that you want to bypass the policy, you could write a small proxy that will listen on your server on port 443 and then, depending on the request, will forward the traffic either to your web server or to the SSH daemon. There are two catches though.
To determine whether it's an HTTPS request or an SSH request, you need to try to read some data with a (small) timeout, this is because TLS/SSL handshakes start with the client sending some data, whereas the SSH handshake starts with the server sending some data. The timeout has to be big enough to delays in delivering the initial data from the client in the TLS/SSL handshake, so it'll make establishing SSH connections slower.
If the HTTP proxy in your company is smart, it'll actually eavesdrop on the expected TLS/SSL "handshake" when you CONNECT to port 443, and, when it detects that it's not an TLS/SSL handshake, it might terminate the SSH connection attempt. To address that, you could wrap the SSH daemon into an TLS/SSL tunnel (e.g., stunnel), but then you'll need to differentiate requests based on the TLS/SSL version in your client request to determine whether to route the TLS/SSL connection to the web server or to the TLS/SSL-tunneled SSH daemon.
You should be able to use iptables to forward ssh traffic from your work machines to ssh while all other machines attaching to your home server on port 443 get the Apache server.
Try a rule like this:
iptables -t nat -A PREROUTING -p tcp -s 111.111.111.111 --dport 443 -j REDIRECT --to-port 22
Where 111.111.111.111 is your office computer's ip address.
That all assumes you're running Linux >= 2.4, which you should be by now. It's been out for almost a decade.
Documentation for iptables is at http://www.netfilter.org.
Set up OpenVPN 2.1 server at home, use port 443 (if you set up your home any HTTPS service at port 443, trigger OpenVPN's port-share option to handle both OpenVPN and HTTPS transactions at port 443; this feature is only available to non-Windows OS)
Then, set up your OpenVPN client on your laptop in road-warrior mode to access the OpenVPN server at home. You will be able to call home or anywhere you like within a secure VPN network you've created with OpenVPN. It is no longer required to use SSH for this purpose.
I'm really sorry for being the Devil's advocate here, but if they are blocking ports at your work, its likely because they don't want people breaching security.
Now if you get permission to open a tunnel from your boss, that's fine, but IF something happens, ANYTHING, and they figure out you have a tunnel, I can almost assure you, you'll become the scapegoat. So if I were you I'd not be opening tunnels at work if they are setting up firewalls against it.
How about using 2 IP adresses on your machine?
Bind apache/https on one IP_1:443 and your sshd on the other IP_2:443?
Could you set up a middle man?
Run a small/free/cheap instance in the cloud listening on 443 for SSH, then though that cloud instance tunnel to your home box on your favorite port - 22 or whatever.
It'll add some latency I'm sure, but it solves the problem of leaving the original home setup intact.
I think you'll have to find a port that you're not using currently that you can get out on, and listen on that. 443 is the obvious candidate, but you say that's not possible. What about mail (25, 110, 143), telnet (23), ftp (21), DNS (53), or even whois (43)?
Proxy tunnel may be your answer
http://proxytunnel.sourceforge.net/
lets say my ssh server is host.domain.tld and my works proxy server is 10.2.4.37
I would add this to my local ssh config
Host host.domain.tld
ProxyCommand /usr/local/bin/proxytunnel -q -p 10.2.4.37:3128 -d %h:%p
ProtocolKeepAlives 30
See:
SSH Through or Over Proxy
http://daniel.haxx.se/docs/sshproxy.html
http://www.agroman.net/corkscrew/
Since apache has no problem whatsoever with CONNECT when no SSL is involved, I turn off SSL features and I use stunnel to serve an https version of my site. This does not require any recompilation, and allows your site to serve https normally. So far, the cleanest workaround I know.
See http://chm.duquesne.free.fr/blog/?p=281 for details.
Must work over port 443, without disturbing other HTTPS traffic (i.e. I can't just put the ssh server on port 443, because I would no longer be able to serve pages over HTTPS)
Is it possible to bind your HTTPS server to a different port? Depending on what it's used for, you may even be able to get around the problem of not being able to directly access it from work by just SSHing home and then using lynx from there.
So, then, give proxifier a try (- it supports HTTP Proxy Server)!
http://www.proxifier.com/documentation/intro.htm
I managed to bypass my company's firewall using the following design via AjaxTerm, it works for me.
PC on company network --> company's proxy via https --> INTERNET --> My home Apache reverse proxy server on SSL + .htpasswd protection --> AjaxTerm Server(From here on ward, I can SSH to any other servers ).
Still not the perfect world... would be good if I can can tunneling to my home network via HTTPS.