⬆️ ⬇️

We fix the hanstunnel on openwrt (calculation of the checksum of the network packet)

Hello. Probably, many people here know the hanstunnel program, which allows you to raise the tunnel on top of ICMP, or rather on ping. I decided to put it on a router openwrt. Collected, started ... Does not work. The symptoms were simple - the packet goes from the router to the external network, but does not arrive at the addressee, while everything works in the local LAN. In this case, the same hans running on a home computer connects outside without question. Who cares how to build a hans package under openwrt and how to make it work - well, under cat.







The first stage is the assembly. How to raise the build environment on my machine is well written on the openwrt site itself, as well as in a bunch of different articles, so I will leave this piece behind the scenes. Suppose we have a toolchain environment and she is able to build standard openwrt packages.

To build the package, we need the hanstunnel source, which can be taken here , as well as the Makefile with the package description, the config file and the init-script file. The last three by chance I found here as a description of the patches. Maybe someone will find direct links, but I already approached. To build your packages, create a folder, for example, custom, put the future package folders in it and direct links from package / feeds / packages to them. I lightly filed a Makefile for the package so that it compiles the sources of their src folder lying next to each other,
that's what happened
 # Copyright (C) 2006 OpenWrt.org
 #
 # This is a free software licensed under the GNU General Public License v2.
 # See / LICENSE for more information.
 #
 # $ Id: Makefile 6008 2007-01-06 18: 39: 10Z nbd $

 include $ (TOPDIR) /rules.mk

 PKG_NAME: = hanstunnel
 PKG_VERSION: = 0.4.3
 PKG_RELEASE: = 1

 PKG_BUILD_DIR: = $ (BUILD_DIR) / $ (PKG_NAME) - $ (PKG_VERSION)

 include $ (INCLUDE_DIR) /package.mk

 define Package / hanstunnel
         SECTION: = net
         CATEGORY: = Network
         SUBMENU: = Firewall Tunnel
         DEPENDS: = + libstdcpp + kmod-tun
         TITLE: = Hans IP over ICMP
         URL: = http: //code.gerade.org/hans/
 endef

 define Package / hanstunnel / description
         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.  endef
 endef

 define Build / Prepare
         echo PREPARE PREPARE
         mkdir -p $ (PKG_BUILD_DIR)
         cp -r ./src/* $ (PKG_BUILD_DIR) /
 endef

 define Build / Compile 
         $ (MAKE) -C $ (PKG_BUILD_DIR) GCC = $ (TARGET_CC) GPP = $ (TARGET_CXX)
 endef 

 
 define Package / hanstunnel / install
         $ (INSTALL_DIR) $ (1) / usr / sbin
         $ (INSTALL_BIN) $ (PKG_BUILD_DIR) / hans $ (1) / usr / sbin /
         $ (INSTALL_DIR) $ (1) /etc/init.d
         $ (INSTALL_BIN) ./files/hans.init $ (1) /etc/init.d/hans
         $ (INSTALL_DIR) $ (1) / etc / config
         $ (INSTALL_CONF) ./files/hans.config $ (1) / etc / config / hans
 endef

 $ (eval $ (call BuildPackage, hanstunnel))




')

The cap of the Makefile of the assembly also had to be slightly filed

Makefile build
 #LDFLAGS + = `sh osflags ld $ (MODE)`
 CFLAGS + = -c -g -DLINUX -DHAVE_LINUX_IF_TUN_H
 TUN_DEV_FILE = src / tun_dev_linux.c
 #GCC = gcc
 #GPP = g ++

 .PHONY: directories

 all: hans

 directories: build_dir

 build_dir:
	 mkdir -p build

 tunemu.o: directories build / tunemu.o

 hans: directories build / tun.o build / sha1.o build / main.o build / client.o build / server.o build / auth.o build / worker.o build / time.o build / tun_dev.o build / echo.o build / exception.o build / utility.o
	 $ (GPP) -o hans build / tun.o build / sha1.o build / main.o build / client.o build / server.o build / auth.o build / worker.o build / time.o build / tun_dev .o build / echo.o build / exception.o build / utility.o $ (LDFLAGS)

 build / utility.o: src / utility.cpp src / utility.h
	 $ (GPP) -c src / utility.cpp -o $ @ -o $ @ $ (CFLAGS)

 build / exception.o: src / exception.cpp src / exception.h
	 $ (GPP) -c src / exception.cpp -o $ @ $ (CFLAGS)

 build / echo.o: src / echo.cpp src / echo.h src / exception.h
	 $ (GPP) -c src / echo.cpp -o $ @ $ (CFLAGS)

 build / tun.o: src / tun.cpp src / tun.h src / exception.h src / utility.h src / tun_dev.h
	 $ (GPP) -c src / tun.cpp -o $ @ $ (CFLAGS)

 build / tun_dev.o:
	 $ (GCC) -c $ (TUN_DEV_FILE) -o build / tun_dev.o -o $ @ $ (CFLAGS)

 build / sha1.o: src / sha1.cpp src / sha1.h
	 $ (GPP) -c src / sha1.cpp -o $ @ $ (CFLAGS)

 build / main.o: src / main.cpp src / client.h src / server.h src / exception.h src / worker.h src / auth.h src / time.h src / echo.h src / tun. h src / tun_dev.h
	 $ (GPP) -c src / main.cpp -o $ @ $ (CFLAGS)

 build / client.o: src / client.cpp src / client.h src / server.h src / exception.h src / config.h src / worker.h src / auth.h src / time.h src / echo. h src / tun.h src / tun_dev.h
	 $ (GPP) -c src / client.cpp -o $ @ $ (CFLAGS)

 build / server.o: src / server.cpp src / server.h src / client.h src / utility.h src / config.h src / worker.h src / auth.h src / time.h src / echo. h src / tun.h src / tun_dev.h
	 $ (GPP) -c src / server.cpp -o $ @ $ (CFLAGS)

 build / auth.o: src / auth.cpp src / auth.h src / sha1.h src / utility.h
	 $ (GPP) -c src / auth.cpp -o $ @ $ (CFLAGS)

 build / worker.o: src / worker.cpp src / worker.h src / tun.h src / exception.h src / time.h src / echo.h src / tun_dev.h src / config.h
	 $ (GPP) -c src / worker.cpp -o $ @ $ (CFLAGS)

 build / time.o: src / time.cpp src / time.h
	 $ (GPP) -c src / time.cpp -o $ @ $ (CFLAGS)

 clean:
	 rm -f build / tun.o build / sha1.o build / main.o build / client.o build / server.o build / auth.o build / worker.o build / time.o build / tun_dev.o build / echo.o build / exception.o build / utility.o build / tunemu.o hans
	 rm -df build

 build / tunemu.o: src / tunemu.h src / tunemu.c
	 $ (GCC) -c src / tunemu.c -o build / tunemu.o






Putting the files in places, you should get something like:



 $ ls -R custom 
 custom:
 hanstunnel

 custom / hanstunnel:
 files makefile src

 custom / hanstunnel / files:
 hans.config hans.init

 custom / hanstunnel / src:
 Makefile osflags src

 custom / hanstunnel / src / src:
 auth.cpp client.h echo.h main.cpp sha1.cpp time.cpp tun_dev_darwin_emu.c tun_dev.h tun_dev_svr4.c tun.h worker.cpp
 auth.h config.h exception.cpp server.cpp sha1.h time.h tun_dev_freebsd.c tun_dev_linux.c tunemu.c utility.cpp worker.h
 client.cpp echo.cpp exception.h server.h sha1_license.txt tun.cpp tun_dev_generic.c tun_dev_openbsd.c tunemu.h utility.h




Next we go to the root buildroot and happily type

 $ make package / feeds / packages / hanstunnel / compile -j5
  make [1] package / feeds / packages / hanstunnel / compile
  make [2] -C package / kernel / linux compile
  make [2] -C package / libs / toolchain compile
  make [2] -C custom / hanstunnel compile




Everything, the package is ready, it lies in the bin folder next to the others.



It remains to check. Here I was waiting for a bummer. With my computer in my home LAN, the tunnel went right up without any questions. Only I was delighted and went to check the connection outside, but, as described above, the packages with openwrt left, and the addressee did not see them. The same situation arose if you run hans on a router in client mode. After much thought, I guessed to remove the ICMP dump and look for the difference between connecting from the router and from my computer. The problem was in the ICMP checksum, which wireshark happily told me about. I honestly took the calculator and went by myself to manually count the amount according to the algorithm prescribed in echo.cpp, which is very similar to the official one . It turned out anything, but not what is needed. As a result, it turned out that the problem is in the odd packet length and MIPS architecture. Good people at the RFC write that the last byte should just be added to the amount, but in fact it is not. We need to add not the last byte, but two bytes, the second of which is 0, which on Big-endian architectures means an increase in our byte multiplied by 256.

Here is the icmpChecksum function:



 uint16_t Echo :: icmpChecksum (const char * data, int length)
 {
     uint16_t * data16 = (uint16_t *) data;
     uint32_t sum = 0;

     for (sum = 0; length> 1; length - = 2)
         sum + = * data16 ++;


     if (length == 1)
     {
         unsigned char tail [2] = {* (unsigned char *) data16, 0};
         sum + = * (uint16_t *) tail;
     }
     while (sum >> 16)
         sum = (sum >> 16) + (sum & 0xffff);

     return ~ sum;
 }




With her, finally, everything worked as it should. Happy end.



UPD : straightened tail for a more beautiful version of jcmvbkbc

Source: https://habr.com/ru/post/211284/



All Articles