[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: two protocols on one port.



On Wed, Sep 12, 2007 at 07:48:46PM +0200, Martin Marcher wrote:
> Hi,
> 
> 2007/9/12, Mumia W.. <paduille.4061.mumia.w+nospam@earthlink.net>:
> > On 09/12/2007 10:51 AM, PETER EASTHOPE wrote:
> > 12.140.16.4 is June. Now you would reconfigure openvpn on May to listen
> > on port 4122. Connections to port 22 on May would be redirected to port
> > 4122 on May only if they come from 12.140.16.4. Otherwise, the
> > connection would go directly May's port 22 which should be running sshd.
> 
> I think what he's asking for is a protocol multiplexer so that the
> multiplexer will be listening on say port 22 and depending on which
> protocol the client is using it will be "delegated" (not using "NATed"
> intentionally) to the correct daemon....which is a piece of software
> that would be useful and something i don't think exists until yet...

It can be done. I am running both ssh and https on port 443 on my machine.
I wrote a little program, designed to run from inetd, to use MSG_PEEK to
see if I'm getting an SSL request and, if so, forward to the web server
(listening for HTTPS on port 442). It can get things wrong on slow
connections, but it works in practice. Something similar (and much easier)
can be used to discriminate based on incoming IP addresses. Here's the code
I'm using (use at your own risk, released to the public domain):

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#ifdef DEBUG_OUTPUT
#include <stdio.h>
#endif
#include <string.h>
#include <unistd.h>

static char *const https[] = {
  "/usr/bin/socket", "-q", "localhost", "442",
  NULL
};
static char *const sshd[] = {
  "/usr/bin/socket", "-q", "localhost", "22",
  NULL
};

int main(int argc, char **argv) {
  struct timeval delay = { 0, 500000 }; /* 0.5 seconds */
  fd_set fds;
  int isHTTPS;

#ifdef DEBUG_OUTPUT
  freopen("/dev/pts/0", "w", stderr);
  fprintf(stderr, "argc = %d\n", argc);
#endif
  if (argc==2) {
    double argdel = atof(argv[1]);
    if (argdel>0) {
      delay.tv_sec = (long)argdel;
      delay.tv_usec = (long)(1000000 * (argdel-delay.tv_sec));
    }
  }
#ifdef DEBUG_OUTPUT
  fprintf(stderr, "delay = %ld.%06ld\n", delay.tv_sec, delay.tv_usec);
#endif
  FD_ZERO(&fds);
  FD_SET(0, &fds);
  if (select(1, &fds, 0, 0, &delay)>0) {
    char buf[] = { 0,0,0,0,0 };
    int result = recv(0, buf, 4, MSG_PEEK);
#ifdef DEBUG_OUTPUT
    perror("Failure?");
#endif
    isHTTPS = ((result!=4) || (strcmp("SSH-", buf)));
#ifdef DEBUG_OUTPUT
    fprintf(stderr, "result = %d, BUF = '%s'\n", result, buf);
#endif
  } else {
    isHTTPS = 0;
  }
  if (isHTTPS) {
#ifdef DEBUG_OUTPUT
    fprintf(stderr, "I think it's HTTPS\n");
#endif
    execv(https[0], https);
  } else {
#ifdef DEBUG_OUTPUT
    fprintf(stderr, "I think it's SSH\n");
#endif
    execv(sshd[0], sshd);
  }
  return 1; /* should never get here */
}

> regards
> martin
--Greg



Reply to: