Guys, I have been successfully using this setup in a prod environment for a over 6 months. Works as expected (OpenSSH-4.7p1, OpenSSH-5.0p1 and OpenSSH-5.1p1) under Solaris and Linux with local and LDAP (pam_ldap) authentication. The setup describes implementation of SSH-Port-Forward-Only gateways with tight destination address:port (per user/group) control without assigning users full UNIX login shells. The configuration takes advantage of (slightly modified) recently implemented OpenSSH 'Match group' feature introduced in OpenSSH-4.3p2 and allows administrators to enforce granular controls of DST IP:PORT combos to which user/groups can open SSH tunnels. It also uses Sleep Dummy Shell (sleepshell) (available at http://www.mariovaldez.net/software/sleepshell/) - simple do-nothing, sleep-forever program that is used as a login shell to avoid full-blown shell assignment. A patch for OpenSSH that allows users to be in multiple "Match group" blocks and allows multiple PermitOpen statements per "Match group" block included bellow. 1. Install sleepshell. Create UNIX accounts with sleepshell as login shell. Create UNIX groups and populate it with users. 2. Apply the patch. Recompile OpenSSH. Install. 3. Modify etc/sshd_config to include groups ands DST IP:Ports combos. part of sshd_config: # disable SSH tunneling globally AllowTcpForwarding no PermitOpen no . . . Match Group web_access AllowTcpForwarding yes PermitOpen WEB_SRV_IP1:443, WEB_SRV_IP1:80, WEB_SRV_IP2:443 Match Group admin_access,ops_guys AllowTcpForwarding yes PermitOpen WEB_SRV_IP1:443, WEB_SRV_IP1:80, WEB_SRV_IP2:443 PermitOpen ADMIN_HOST1:22, ADMIN_HOST2:80 PermitOpen THIS_HOST:443, WIN_HOST:3389 # allow root to tunnel everywhere # 'any' appears to be undocumented Match Group root AllowTcpForwarding yes PermitOpen any +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ And the patch: --- servconf.c 2008-07-03 23:51:12.000000000 -0400 +++ openssh-5.1p1-EQU/servconf.c 2008-07-25 14:05:57.259529000 -0400 @@ -1244,8 +1244,12 @@ } break; } +/* + + if (*activep && n == -1) channel_clear_adm_permitted_opens(); +*/ for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { p = hpdelim(&arg); if (p == NULL) @@ -1255,7 +1259,10 @@ if (arg == NULL || (port = a2port(arg)) == 0) fatal("%s line %d: bad port number in " "PermitOpen", filename, linenum); +/* if (*activep && n == -1) +*/ + if (*activep && n != 0) options->num_permitted_opens = channel_add_adm_permitted_opens(p, port); } --- ssh.h 2006-08-04 22:39:41.000000000 -0400 +++ openssh-5.1p1-EQU/ssh.h 2008-07-25 14:05:57.286394000 -0400 @@ -19,7 +19,11 @@ #define SSH_DEFAULT_PORT 22 /* Maximum number of TCP/IP ports forwarded per direction. */ -#define SSH_MAX_FORWARDS_PER_DIRECTION 100 + +/* EQU modification */ +/* #define SSH_MAX_FORWARDS_PER_DIRECTION 100 */ + +#define SSH_MAX_FORWARDS_PER_DIRECTION 65536 /* * Maximum number of RSA authentication identity files that can be specified -- .signature: No such file or directory