Bits and Chaos

Icon

Between bits and chaos, a sysadmin stands.

Squid over SSH

At work we need to externally access some intranet sites that are not visible on the Internet, both for architectural deployment and security concerns.

I manage this with an SSH tunnel and Squid access over it. Security is my first requirement for this kind of remote access, and this configuration will maximize it.

Configuring SSH server on the gateway

First, I work on an SSH externally accessible server that will act as a gateway, configuring the sshd running on it to refuse root login, allowing for TCP port forwarding and gateways. SSHD will listen on a non standard port, to avoid automated attacks from bots:

from /etc/ssh/sshd_config on the gateway:

Port 12345   # use a more strange number for your configuration
PermitRootLogin no
AllowTcpForwarding yes
GatewayPorts yes
X11Forwarding yes

on this gateway, I have only one user account, remoteaccess, with no password. This means that access will be only possible with certificates. After modifications, restart SSH server.

For and on each trustworthy client, I create a certificate on it:

client> ssh-keygen -t dsa

and the resulting public certificate, $HOME/.ssh/id_dsa.pub, has to be added to the authorized keys for the remoteaccess user on the gateway machine:

gateway> cat id_dsa.pub >> /home/remoteaccess/.ssh/authorized_keys

If you are paranoid, you can limit the number of tentative connections made on the gateway machine with some iptables rules. Add to /etc/sysconfig/iptables:

-A INPUT -s WHITELISTNETWORK1 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -s WHITELISTNETWORK2 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180
         --hitcount 3 --name DEFAULT --rsource -j DROP
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT
         --rsource -j ACCEPT

if you add these rules, then restart iptables for the new configuration to take effect. The proposed rules will drop an IP when it originates more than 3 connections in 180 seconds. Note that this is made at TCP level, so even successful and legitimate connections are counted. This is why it’s good to white list some IPs (like localhost) or networks (like 10.0.0.0 or whatever).

In my experience, this specific hardening is not required, because it’s sufficient that your SSH server is listening on a non standard port to remove accesses from standard bots, where more sophisticated attack swill be stopped by the SSH certificate-only access. But if you are really paranoid, you can also add portknocking enabled access to your SSH server.

Remember that this gateway must always be updated for critical security fixes. It could be good if it’s running a different operating system than the rest of your infrastructure (e.g. a BSD flavour if you are a Linux shop) because, at the cost of some more management and administration effort, you avoid that the same zero-day security flaw will target all of your systems (this is not necessarily true, because you may end up running the same software on different Unixes, so evaluate pros and cons carefully).

Check that SSH connection is working:

client> ssh -P 12345 remoteaccess@gateway

it works if you have access on the gateway without being asked for a password.

Configuring Squid

Squid will run on the gateway, accepting only proxying requests from clients running on the gateway machine. This could be accomplished in some different ways:

  • configuring squid to accept only requests from 127.0.0.1;
  • definining a iptables rule that stops foreign requests;
  • configuring the external firewall to stop external requests for Squid.

As defense in deep is a good security practice, it’s better if you do all of these: would one of them falling apart, the others will save the day.

The iptables rules:

gateway> iptables -A INPUT -p tcp -m tcp --source 127.0.0.1 --dport 3128 -j ACCEPT
gateway> iptables -A INPUT -p tcp -m tcp --dport 3128 -j DROP

After definition of them, save the new iptables configuration (service iptables save) and restart the service (service iptables restart). As a result, only TCP connections originated from 127.0.0.1 on port 3128 (the standard port of Squid, and there is no need to work on a non default port) are accepted.

Configuration for Squid is made on the (big) /etc/squid/squid.conf file. Critical parameters are:

acl INTRANET dstdomain .intranet.example.com critical.example.com
http_access allow INTRANET
http_access deny all

These three lines defines an acl named INTRANET, that allows for proxying of HTTP request for the critical.example.com server and the *.intranet.example.com domain. These rules must be added (in Squid order of configuration directives is critical) after this point:

# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS

# Example rule allowing access from your local networks. Adapt
# to list your (internal) IP networks from where browsing should
# be allowed
#acl our_networks src 192.168.1.0/24 192.168.2.0/24
#http_access allow our_networks

Note that if you want defense in deep, uncomment the last two lines, defining suitable values for our_networks (our_networks src 127.0.0.1/32)

The configuration above is for RHEL 4.x, which ships Squid 2.4. If you have RHEL 5.x, you have Squid 2.5 that allows for password authentication. In such a case, use these configuration rules:

auth_param digest program /usr/lib/squid/digest_pw_auth /etc/squid/password.txt
auth_param digest realm Example.com Intranet Access
auth_param digest children 2
auth_param digest nonce_max_duration 8 hours
auth_param digest nonce_max_count 1000
acl AUTHUSER proxy_auth REQUIRED
acl INTRANET dstdomain .intranet.example.com critical.example.com

http_access allow INTRANET AUTHUSER

http_access deny all

The file /etc/squid/password.txt will be a simple line:

username:password

Use more lines if you want to discrimate between users. (More authentication schemas are available for Squid). Now (re)start Squid on the gateway.

Client configuration

First, create the SSH tunnel:

client> ssh -l remoteuser -N -T -p 12345  -L 3128:localhost:3128 gateway-hostname-or-public-ip-address

so a connection on the local 3128 port of the localhost will be SSH tunnelled to the port 3128 of the gateway, where Squid is eagerly listening.

Then we need to instruct the client’s browser to proxy request for the intranet domain to port 3128 on localhost, with a Proxy Auto Configuration (PAC) file.

A PAC file example is:

function FindProxyForURL(url, host)
{
  if (shExpMatch(host, "*intranet.example.com"))
    return "PROXY 127.0.0.1:3128";

  if (shExpMatch(host, "critical.example.com"))
    return "PROXY 127.0.0.1:3128";

  return "DIRECT";

}

This file could be put on a web server where it could be accessed for all the clients, or distributed via e-mail, it’s not security sensitive.

After all these steps done, you will access your intranet via SSH, which means you could work even on Sundays.

Advertisements

Filed under: rhel, , ,

2 Responses

  1. Xtecuan! Ufo says:

    Thanks for the information, this article help me to improve the security of my home network

  2. thanks, I’ve been having trouble setting up squid proxy server on my vps btu that has helped me a lot

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: