diff --git a/README b/README new file mode 100644 index 0000000..7043a12 --- /dev/null +++ b/README @@ -0,0 +1,16 @@ +### Compiling ### + +make + +### Running as a server ### + +./hans -s 10.1.2.0 -r -p password -u nobody +echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all + +### Running as a client ### + +./hans -c server_address -p password -u nobody + +### Help ### + +./hans diff --git a/client.cpp b/client.cpp index 22c1e45..accc140 100644 --- a/client.cpp +++ b/client.cpp @@ -78,9 +78,9 @@ void Client::sendChallengeResponse(int dataLength) setTimeout(5000); } -bool Client::handleEchoData(TunnelHeader header, int dataLength, uint32_t realIp, bool reply, int id, int seq) +bool Client::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, int id, int seq) { - if (realIp != serverIp || !reply || id != ICMP_ID) + if (realIp != serverIp || !reply) return false; if (header.magic != Server::magic) diff --git a/client.h b/client.h index dbd732f..6fdf905 100644 --- a/client.h +++ b/client.h @@ -43,7 +43,7 @@ protected: STATE_ESTABLISHED }; - virtual bool handleEchoData(TunnelHeader header, int dataLength, uint32_t realIp, bool reply, int id, int seq); + virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, int id, int seq); virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp); virtual void handleTimeout(); diff --git a/main.cpp b/main.cpp index 601f9bd..38ac4c4 100644 --- a/main.cpp +++ b/main.cpp @@ -33,8 +33,30 @@ void usage() { printf( - "usage: hans -s network [-fhr] [-p password] [-u unprivileged_user] [-d tun_device] [-m mtu]\n" - " hans -c server [-fhw] [-p password] [-u unprivileged_user] [-d tun_device] [-m mtu]\n"); + "Hans - IP over ICMP version 0.1 dev\n\n" + "RUN AS SERVER\n" + " hans -s network [-fr] [-p password] [-u unprivileged_user] [-d tun_device] [-m reference_mtu]\n\n" + "RUN AS CLIENT\n" + " hans -c server [-f] [-p password] [-u unprivileged_user] [-d tun_device] [-m reference_mtu] [-w polls]\n\n" + "ARGUMENTS\n" + " -s network Run as a server with the given network address for the virtual interface.\n" + " -c server Connect to a server.\n" + " -f Run in foreground.\n" + " -r Respond to ordinary pings. Only in server mode.\n" + " Use this when you disable echo replies of your operating system, which is a good idea.\n" + " -p password Use a password.\n" + " -u username Set the user under which the program should run.\n" + " -d device Use the given tun device.\n" + " -m mtu Use this mtu to calculate the tunnel mtu.\n" + " The generated ICMP packets will not be bigger than this value.\n" + " Has to be the same on client and server.\n" + " In most cases you don't want to set this. Defaults to 1500.\n" + " -w polls Number of echo requests the client sends to the server for polling.\n" + " If your network allows unlimited echo replies set this to 0 to disable polling.\n" + " The default value of 10 is regarded as pretty high.\n" + " Set this to a lower value if you experience packet loss through the tunnel.\n" + " Set this to 1 in extreme cases, when your network allows only one echo reply per request.\n" + " A low value will decrease the performance of the tunnel.\n"); } int main(int argc, char *argv[]) @@ -56,15 +78,12 @@ int main(int argc, char *argv[]) openlog(argv[0], LOG_PERROR, LOG_DAEMON); int c; - while ((c = getopt(argc, argv, "fhru:d:p:s:c:m:w:")) != -1) + while ((c = getopt(argc, argv, "fru:d:p:s:c:m:w:")) != -1) { switch(c) { case 'f': foreground = true; break; - case 'h': - usage(); - return 0; case 'u': userName = optarg; break; @@ -100,19 +119,16 @@ int main(int argc, char *argv[]) mtu -= Echo::headerSize() + Worker::headerSize(); - if (isClient == isServer) + if (mtu < 68) { - usage(); + // RFC 791: Every internet module must be able to forward a datagram of 68 octets without further fragmentation. + printf("mtu too small\n"); return 1; } - if (network == INADDR_NONE && isServer) - { - usage(); - return 1; - } - - if (maxPolls < 0 || maxPolls > 255) + if ((isClient == isServer) || + (isServer && network == INADDR_NONE) || + (maxPolls < 0 || maxPolls > 255)) { usage(); return 1; diff --git a/server.cpp b/server.cpp index 373b685..9db42fb 100644 --- a/server.cpp +++ b/server.cpp @@ -49,7 +49,7 @@ Server::~Server() } -void Server::handleUnknownClient(TunnelHeader &header, int dataLength, uint32_t realIp) +void Server::handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp) { ClientData client; client.realIp = realIp; @@ -146,9 +146,9 @@ void Server::sendReset(ClientData *client) sendEchoToClient(client, TunnelHeader::TYPE_RESET_CONNECTION, 0); } -bool Server::handleEchoData(TunnelHeader header, int dataLength, uint32_t realIp, bool reply, int id, int seq) +bool Server::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, int id, int seq) { - if (reply || id != ICMP_ID) + if (reply) return false; if (header.magic != Client::magic) diff --git a/server.h b/server.h index 4c116db..7686571 100644 --- a/server.h +++ b/server.h @@ -74,7 +74,7 @@ protected: typedef std::vector ClientList; typedef std::map ClientIpMap; - virtual bool handleEchoData(TunnelHeader header, int dataLength, uint32_t realIp, bool reply, int id, int seq); + virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, int id, int seq); virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp); virtual void handleTimeout(); @@ -82,7 +82,7 @@ protected: void serveTun(ClientData *client); - void handleUnknownClient(TunnelHeader &header, int dataLength, uint32_t realIp); + void handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp); void removeClient(ClientData *client); void sendChallenge(ClientData *client); diff --git a/worker.h b/worker.h index 3499e24..e7f5890 100644 --- a/worker.h +++ b/worker.h @@ -41,7 +41,9 @@ protected: { struct Magic { + Magic() { } Magic(const char *magic); + bool operator==(const Magic &other) const; bool operator!=(const Magic &other) const; @@ -65,11 +67,11 @@ protected: }; }; // size = 5 - virtual bool handleEchoData(TunnelHeader header, int dataLength, uint32_t realIp, bool reply, int id, int seq) { return true; } + virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, int id, int seq) { return true; } virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp) { } virtual void handleTimeout() { } - void sendEcho(const TunnelHeader::Magic &magic, int type, int length, uint32_t realIp, bool reply, int id, int seq); + void sendEcho(const TunnelHeader::Magic &magic, uint16_t pollSequence, int type, int length, uint32_t realIp, bool reply, int id, int seq); void sendToTun(int length); void setTimeout(Time delta);