Re: IP TUNNEL / was Re: doesn't anybody use tunnelling / vpn?
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;
}
}
Reply to: