Q: how to restrict access selectively to client initiated local port forward

Michael O'Cleirigh mocleiri at jpint.utoronto.ca
Sat Sep 29 00:36:32 EST 2007


First, thanks for all the feedback to my question.   

>> Then you should run OpenVPN over TCP on port 22 or whatever you're
>> using for SSH that can be reached from clients, on another public IP
>> address and be done.
> This is likely the correct solution.
I hadn't done this because the OpenVPN Documentation recommends not 
tunneling TCP/IP through TCP/IP but I see know that thats exactly what 
ssh is doing anyways.

>>> However as far as I can tell there is no way in OpenSSH to define
>>> an access control policy for which connecting users are allowed to
>>> redirect through which local IP.
>> Right, because there's no way for OpenSSH to implement it anyway.
> You are right in that it can't be done in the base OpenSSH code. 
> However, I know it can be done with patches to OpenSSH because we 
> actually implemented it. We even had it so that one user wouldn't be 
> able bogart well known ports. So it can be done. Its just not easy and 
> probably not worth the hassle in this instance.

I finally figured out how to modify the OpenSSH source to hook in my 
module.   Here are some of the details for the benefit of the people 
searching the list archives in the future:

Our module reads a custom passwd file that contains:
1. username
2. password
3. list of common names they are allowed to connect to (in our setup all 
common names have a client configuration directory file; the module will 
parse this file to extract the IP that is allowed to accessed by that 

We have an OpenVPN authentication plugin and a PAM module that also use 
the same core module authenticating our users for this proxy. 

For OpenSSH the modification is to change how the 
channels.c:channel_connect_to(...) method works from checking the 
permitted_open array which is setup at startup to checking my 
configuration files which are changeable at runtime. 

We modify channels.c:channel_connect_to() as follows:

1. Add a new parameter of type Authctxt* which is passed in from the 
serverloop.c as the_authctxt and NULL everywhere else. This holds the 
username which is what we need for testing the allowability of a given 
(username, host) tcp forward.

2. The comment 'channel_connect_to' was: /* XXX check permission */ 
which turned out to indicate the insertion point for my method: 
_is_tcp_forward_allowed ().

3. Change the names of a few structures in sshconnect2.c which overlap 
with Authctxt, Authmethod as defined in auth.h (vim global replace is 
all that is required).  This is because channels.h needs to be modified 
for the channel_connect_to prototype and is used in a wider context.

4. The new method works like:

/* Check if connecting to that port is permitted and connect. */
channel_connect_to(const char *host, u_short port, Authctxt *authctxt)
    error ("channel_connect_to: host=%s, port = %d\n", host, port);
    if (authctxt != NULL) {
        if (_is_tcp_forward_allowed ("/etc/proxy_passwd", 
"/etc/openvpn/ccd", authctxt->user, host) == 0)    {
            logit("Proxy Extension: Port forwarding NOT permitted 
(user=%s, host=%s).", authctxt->user, host);
            return -1;
        else {
            /* fall through to initiate the request */
            logit("Proxy Extension: Port forwarding IS permitted 
(user=%s, host=%s).", authctxt->user, host);


    return connect_to(host, port);

Thanks again,


More information about the openssh-unix-dev mailing list