On Wed, 27 Sep 2000, will trillich wrote: > hi. i have no clue about all this fancy stuff. sounds > delightfully cool. if you get it straightened out, > PLEASE post a 'SOLVED' message so that the rest of us > dunces (speaking for what i hope is a large group and > not just me) can learn from your experience... > > by the way -- HOW did you set up those tunnels? > > what package, what command, what script? >
OK I'm a bit hesitant about posting my solution since I figure there's probably a simpler and better way, but here goes. Please note that I'm only doing this because it's the only way I know for e.g. reading news on my school's news server, given that my ISP is LargeFacelessCorporation.com and not my school's modem pool. I'm not doing it just because it's a neat trick or whatever. Peace. First, I put the following two lines in the "iface eth0" section of my /etc/network/interfaces. (I talk to the world through an ethernet card, if this is not the way you do things you'll have to find some other way, like your /etc/ppp/ip-up script or whatever): up /etc/init.d/tcp-pipes start down /etc/init.d/tcp-pipes stop The "tcp-pipes" script is attached. The way I do it, this script runs a command on the remote machine. The command does nothing: it just hangs. I've jimmied things on the other end so that only one instance of this command (there's actually three of them, they're called "imapl, newsl, and maill" if I remember right) can run at a time. Otherwise, I'd eventually have a million of these things running on the remote machine and the sysadmins at school would hate me. I've done this with a C program (attached) which reads a PID from a file, nukes the process, writes its PID to the same file, and hangs forever. You can maybe do the same thing with a shell script. Uh, I think that's all. Then I just tell my mail and news clients to talk to, say, port 6143 on the localhost instead of port 143 on the remote host. Hope this helps. -chris
#! /bin/sh # # Port forwarding to servers which would otherwise refuse connections from us # echo $* NAME=`basename $0` PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin SSH=/usr/bin/ssh2 # careful! there might be an ssh in the current dir SSHBASENAME=`basename ${SSH}` SSHFLAGS="-f -x" HOST=cascade.cs.ubc.ca USER=majewski PRG=loop start() { LOCALPORT=$1 DEST=$2 REMOTEPORT=$3 PIPE=$4 SSHARGS="${SSHFLAGS} -l ${USER} -L ${LOCALPORT}:${DEST}:${REMOTEPORT} ${HOST} ${PIPE}l" PIDFILE=/var/run/${PIPE}-pipe.pid # echo -n "Starting ${PIPE}: " if [ -e ${PIDFILE} ]; then rm ${PIDFILE} fi start-stop-daemon --start --verbose --background --make-pidfile --pidfile ${PIDFILE} --exec ${SSH} -- ${SSHARGS} if [ $? -eq 0 ]; then fixpid ${PIPE} ${PIDFILE} fi # echo "${PIPE}." } # Wait for the PIDFILE to get the initial PID of the ssh process # Wait for the ssh process to exec() to a different PID # Put the new PID in the PIDFILE fixpid() { PIPE=$1 PIDFILE=$2 PID= NEWPID= COUNT=1 MAXCOUNT=10 GOTCHA=false while [ "${PID}" = "" ]; do if [ ${COUNT} -gt ${MAXCOUNT} ]; then logger "${NAME}: initial PID not found for ${PIPE}" logger "${NAME}: continuing anyway..." break fi if [ -e ${PIDFILE} ]; then PID=`cat ${PIDFILE}` fi COUNT=`expr ${COUNT} + 1` sleep 1 done # sleep until the process with the old PID goes away # can't use 'wait' because the ssh process is not our child COUNT=1 while ps h -o pid -p ${PID} >> /dev/null; do if [ ${COUNT} -gt ${MAXCOUNT} ]; then logger "${NAME}: new PID not found for ${PIPE}" logger "${NAME}: continuing anyway..." break fi COUNT=`expr ${COUNT} + 1` GOTCHA=true sleep 1 done NEWPID=`ps h -C ${SSHBASENAME} | grep ${PIPE} | awk '{print $1}'` if [ "${NEWPID}" = "" ]; then logger "${NAME}: Empty PID, you may have to stop ${PIPE} manually later on" else echo ${NEWPID} > ${PIDFILE} fi } stop() { PIPE=$1 PID= # echo -n "Stopping ${PIPE}: " PIDFILE=/var/run/${PIPE}-pipe.pid start-stop-daemon --stop --verbose --pidfile ${PIDFILE} if [ $? -ne 0 ]; then PID=`ps h -C ${SSHBASENAME} | grep ${PIPE} | awk '{print $1}'` if [ "${PID}" != "" ]; then echo "Killing ${PIPE} pipe by brute force" logger "${NAME}: Killing ${PIPE} pipe by brute force" # ask process to die honorably kill -TERM ${PID} # coup de grace if necessary PID=`ps h -C ${SSHBASENAME} | grep ${PIPE} | awk '{print $1}'` if [ "${PID}" != "" ]; then kill -KILL ${PID} fi else logger "${NAME}: Couldn't find PID for ${PIPE}, not killing" fi fi rm -f ${PIDFILE} # echo "${PIPE}." } startImap() { start 6143 imap.cs.ubc.ca 143 imap } startNews() { start 6119 news.cs.ubc.ca 119 news } startMail() { start 6025 mailhost.cs.ubc.ca 25 mail } startAll() { echo "Starting ${NAME}: " start 6143 imap.cs.ubc.ca 143 imap start 6119 news.cs.ubc.ca 119 news start 6025 mailhost.cs.ubc.ca 25 mail echo "${NAME}." } stopAll() { echo "Stopping ${NAME}: " stop imap stop news stop mail echo "${NAME}." } case "$1" in imap) startImap ;; news) startNews ;; mail) startMail ;; start) startAll ;; stop) stopAll ;; restart) stopAll startAll ;; #reload) # # If the daemon can reload its config files on the fly # for example by sending it SIGHUP, do it here. # # If the daemon responds to changes in its config file # directly anyway, make this a do-nothing entry. # # echo "Reloading $DESC configuration files." # start-stop-daemon --stop --signal 1 --quiet --pidfile \ # /var/run/$NAME.pid --exec $DAEMON #;; # restart|force-reload) # # # # If the "reload" option is implemented, move the "force-reload" # # option to the "reload" entry above. If not, "force-reload" is # # just the same as "restart". # # # echo -n "Restarting $DESC: " # start-stop-daemon --stop --quiet --pidfile \ # /var/run/$NAME.pid --exec $DAEMON # sleep 1 # start-stop-daemon --start --quiet --pidfile \ # /var/run/$NAME.pid --exec $DAEMON # echo "$NAME." # ;; *) N=/etc/init.d/${NAME} # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 # echo "Usage: $N {start|stop|restart|force-reload}" >&2 echo "Usage: $N {start|stop}" >&2 exit 1 ;; esac exit 0
#include <stdio.h> #include <unistd.h> #include <strings.h> #include <sys/types.h> #include <signal.h> #include <stdlib.h> #include <malloc.h> #include <libgen.h> int main(int arc, const char** argv) { const char* home = getenv("HOME"); char* fullName = (char *)malloc(1000*sizeof(char)); char* name = NULL; pid_t pid = getpid(); pid_t previousPid = 0; char* fileName = (char*)malloc(1000*sizeof(char)); FILE* file = NULL; int _signal = 9; strcpy(fullName, argv[0]); name = basename(fullName); fileName[0] = (char)0; strcat(fileName, home); strcat(fileName, "/var/run/"); strcat(fileName, name); strcat(fileName, ".pid"); file = fopen(fileName, "r"); if (file == NULL) { fprintf(stderr, "Failed to open file '%s' for reading\n", fileName); exit(1); } fscanf(file, "%d", &previousPid); if (previousPid != pid) { if (previousPid > 0) { /* There is a race condition here. If we kill the old instance before overwriting its PID, a third instance could try to kill a nonexistent process. If on the other hand we overwrite the PID first, a third instance could kill us before we have a chance to kill the old instance. */ int result = kill(previousPid, _signal); if (result != 0) { fprintf(stderr, "Failed to kill PID '%d' with signal '%d'\n" "Continuing anyway...\n", previousPid, _signal); } } } else { fprintf(stderr, "Suicide attempt thwarted\n"); exit(1); } { int result; fclose(file); file = fopen(fileName, "w"); if (file == NULL) { fprintf(stderr, "Failed to open file '%s' for writing\n", fileName); exit(1); } fprintf(file, "%d", pid); fflush(file); fclose(file); result = pause(); fprintf(stderr, "pause() returned value '%d'\n", result); return 0; } }