diff --git a/Makefile b/Makefile index 332f3d4..27c382e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ LDFLAGS = `sh osflags ld $(MODE)` -CFLAGS = -c -g `sh osflags c $(MODE)` -CPPFLAGS = -c -g -std=c++98 -pedantic -Wall -Wextra -Wno-sign-compare -Wno-missing-field-initializers `sh osflags c $(MODE)` +CFLAGS = -c -g -O2 `sh osflags c $(MODE)` +CPPFLAGS = -c -g -O2 -std=c++98 -pedantic -Wall -Wextra -Wno-sign-compare -Wno-missing-field-initializers `sh osflags c $(MODE)` TUN_DEV_FILE = `sh osflags dev $(MODE)` GCC = gcc GPP = g++ diff --git a/README.md b/README.md index 9ab9e2e..3e2ffbf 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,22 @@ Hans - IP over ICMP Hans makes it possible to tunnel IPv4 through ICMP echo packets, so you could call it a ping tunnel. This can be useful when you find yourself in the situation that your Internet access is firewalled, but pings are allowed. http://code.gerade.org/hans/ + +This repo adds the minimal necessary code changes for the code to be able to compile inside a [Termux](https://github.com/termux/termux-app) Android environment (inside the own device!). + +Building and running instructions: +* For manipulating ICMP packets you need a rooted device. +* Install [Termux app](https://github.com/termux/termux-app), and then install the clang compiler and make: `pkg install clang make` +* Clone this repo and then you should be able to compile a binary from within your device with `make` +* Adapt and exec the hans_android.sh script (as root!) inside the repo, in my experience the "main" routing table needs to be added to `ip rule` for the Hans tunnel packets to be routed correctly. Also the binary outputs to logcat, this is handled in the script as well (good for debugging). +* These changes have not been tested with multiple devices or Android versions, it has been tested with an Android 10 device. If you encounter problems you'll possibly need to debug them with strace or ltrace. +* Systemd example service unit file and conf file are included as convenience. + +Refs: +* https://github.com/friedrich/hans +* http://code.gerade.org/hans/ +* https://github.com/raidenii/hans-android +* https://nethack.ch/2016/12/10/how-to-use-openvpn-over-an-ip-over-icmp-tunnel-hans/ +* https://hundeboll.net/internet-tunneling-through-icmp.html + +Happy ICMP tunneling ;) diff --git a/hans-server.service b/hans-server.service new file mode 100644 index 0000000..f5c2c52 --- /dev/null +++ b/hans-server.service @@ -0,0 +1,13 @@ +[Unit] +Description=Hans IP over ICMP tunneling daemon +After=syslog.target network-online.target +Wants=network-online.target + +[Service] +Type=forking +EnvironmentFile=/opt/hans/hans.conf +Restart=on-abort +ExecStart=/opt/hans/hans -s $IP -p $PASS -u $USER + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/hans.conf b/hans.conf new file mode 100644 index 0000000..e1baefd --- /dev/null +++ b/hans.conf @@ -0,0 +1,3 @@ +IP=10.0.0.1 +PASS=change_this_password +USER=nobody \ No newline at end of file diff --git a/hans_android.sh b/hans_android.sh new file mode 100644 index 0000000..6a9bb83 --- /dev/null +++ b/hans_android.sh @@ -0,0 +1,9 @@ +#!/data/data/com.termux/files/usr/bin/bash + +hans="/data/data/com.termux/files/home/hans/hans" + +$hans -c 172.16.0.1 -p change_this_password -v +ip rule add from all lookup main pref 1 +bash -c "trap 'exit 0' INT; logcat -v color | grep $hans" +killall $hans +ip rule del from all lookup main pref 1 \ No newline at end of file diff --git a/osflags b/osflags index fb41a49..3515718 100644 --- a/osflags +++ b/osflags @@ -16,7 +16,11 @@ ld) c) case $OS in LINUX) - echo $FLAGS -DHAVE_LINUX_IF_TUN_H -DLINUX + if [ `uname -o | tr "a-z" "A-Z"` = "ANDROID" ]; then + echo $FLAGS -DHAVE_LINUX_IF_TUN_H -DLINUX -DANDROID + else + echo $FLAGS -DHAVE_LINUX_IF_TUN_H -DLINUX + fi ;; CYGWIN*) echo $FLAGS -DWIN32 diff --git a/src/main.cpp b/src/main.cpp index 99b1226..e5d1624 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,12 @@ #define AI_V4MAPPED 0 #endif +#ifdef ANDROID +#define AI_FLAGS (AI_ADDRCONFIG) +#else +#define AI_FLAGS (AI_V4MAPPED | AI_ADDRCONFIG) +#endif + using std::string; static Worker *worker = NULL; @@ -226,7 +232,7 @@ int main(int argc, char *argv[]) struct addrinfo *res = NULL; hints.ai_family = AF_INET; - hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; + hints.ai_flags = AI_FLAGS; int err = getaddrinfo(serverName.data(), NULL, &hints, &res); if (err) diff --git a/src/tun.cpp b/src/tun.cpp index 8bfeb58..3beb092 100644 --- a/src/tun.cpp +++ b/src/tun.cpp @@ -36,6 +36,12 @@ #include #endif +#ifdef ANDROID +#define IFCONFIG_PATH "ifconfig " +#else +#define IFCONFIG_PATH "/sbin/ifconfig " +#endif + typedef ip IpHeader; using std::string; @@ -77,7 +83,7 @@ Tun::Tun(const string *device, int mtu) << "\" mtu=" << mtu; winsystem(cmdline.str().data()); #else - cmdline << "/sbin/ifconfig " << this->device << " mtu " << mtu; + cmdline << IFCONFIG_PATH << this->device << " mtu " << mtu; if (system(cmdline.str().data()) != 0) syslog(LOG_ERR, "could not set tun device mtu"); #endif @@ -102,11 +108,11 @@ void Tun::setIp(uint32_t ip, uint32_t destIp) if (!tun_set_ip(fd, ip, ip & 0xffffff00, 0xffffff00)) syslog(LOG_ERR, "could not set tun device driver ip address: %s", tun_last_error()); #elif LINUX - cmdline << "/sbin/ifconfig " << device << " " << ips << " netmask 255.255.255.0"; + cmdline << IFCONFIG_PATH << device << " " << ips << " netmask 255.255.255.0"; if (system(cmdline.str().data()) != 0) syslog(LOG_ERR, "could not set tun device ip address"); #else - cmdline << "/sbin/ifconfig " << device << " " << ips << " " << destIps + cmdline << IFCONFIG_PATH << device << " " << ips << " " << destIps << " netmask 255.255.255.255"; if (system(cmdline.str().data()) != 0) syslog(LOG_ERR, "could not set tun device ip address"); diff --git a/src/tun_dev_linux.c b/src/tun_dev_linux.c index 0179eac..6e7bfc4 100644 --- a/src/tun_dev_linux.c +++ b/src/tun_dev_linux.c @@ -37,6 +37,12 @@ /* #include "vtun.h" #include "lib.h" */ +#ifdef ANDROID +#define TUN_PATH "/dev/tun" +#else +#define TUN_PATH "/dev/net/tun" +#endif + /* * Allocate TUN device, returns opened fd. * Stores dev name in the first arg(must be large enough). @@ -87,7 +93,7 @@ static int tun_open_common(char *dev, int istun) struct ifreq ifr; int fd; - if ((fd = open("/dev/net/tun", O_RDWR)) < 0) + if ((fd = open(TUN_PATH, O_RDWR)) < 0) return tun_open_common0(dev, istun); memset(&ifr, 0, sizeof(ifr));