diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02de31b..d60e4da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,14 +37,14 @@ jobs: if: github.event_name != 'release' uses: actions/upload-artifact@v3 with: - name: dpitunnel-cli-${{ matrix.arch }} - path: build/DPITunnel-cli-exec + name: dpitunnel-${{ matrix.arch }} + path: build/DPITunnel-exec - name: Upload Binary to Release if: github.event_name == 'release' uses: svenstaro/upload-release-action@2.7.0 with: repo_token: ${{ secrets.GITHUB_TOKEN }} - file: build/DPITunnel-cli-exec - asset_name: dpitunnel-cli-${{ matrix.arch }} + file: build/DPITunnel-exec + asset_name: dpitunnel-${{ matrix.arch }} tag: ${{ github.ref }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 927001d..69ac884 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ add_executable(DPITunnel-exec socket.cpp ssl.cpp utils.cpp - ) +) if (STATIC_BINARY) target_link_libraries(DPITunnel-exec -static) @@ -52,7 +52,7 @@ find_package(httplib 0.13.3 COMPONENTS OpenSSL ZLIB Brotli) if (NOT HTTPLIB_FOUND) add_subdirectory(cpp-httplib) message(STATUS "Using bundled httplib") -endif() +endif () # Add libnl (libnl) find_package(LibNL REQUIRED) @@ -64,7 +64,7 @@ target_include_directories(DPITunnel-exec ${PROJECT_SOURCE_DIR}/RawSocket/include ${PROJECT_SOURCE_DIR}/dnslib/include ${LibNL_INCLUDE_DIR} - ) +) target_link_libraries(DPITunnel-exec RawSocket @@ -75,7 +75,7 @@ target_link_libraries(DPITunnel-exec Threads::Threads OpenSSL::SSL OpenSSL::Crypto - ) +) if (STATIC_BINARY) target_link_libraries(DPITunnel-exec ${CMAKE_DL_LIBS}) diff --git a/README.md b/README.md index 1374651..d3c9b1d 100644 --- a/README.md +++ b/README.md @@ -9,94 +9,124 @@ Free, simple and serverless solution against censorship for Linux PCs and router ### What is it + DPI Tunnel is a proxy server, that allows you to bypass censorship -It is NOT VPN and won't change your IP +It is NOT a VPN and will NOT change your IP DPI Tunnel uses desync attacks to fool DPI filters RUN IT AS ROOT ### Features + * Bypass many restrictions: blocked or throttled resources -* Create profiles for different ISP and automatically change them when switch connection -* Easily auto configure for your ISP +* Create profiles for different ISPs and automatically change them when the connection switches +* Easily autoconfigure for your ISP * Has HTTP and transparent proxy modes ## Configuring -#### For the most of ISPs one of the these 2 profiles will be enough: -``` + +### For most of the ISPs, one of the these 2 profiles will be enough + +```shell --ca-bundle-path= --desync-attacks=fake,disorder_fake --split-position=2 --auto-ttl=1-4-10 --min-ttl=3 --doh --doh-server=https://dns.google/dns-query --wsize=1 --wsfactor=6 ``` -``` + +```shell --ca-bundle-path= --desync-attacks=fake,disorder_fake --split-position=2 --wrong-seq --doh --doh-server=https://dns.google/dns-query --wsize=1 --wsfactor=6 ``` -*CA Bundle is a file that contains root and intermediate SSL certificates. Required for DoH and autoconfig to work. You can get it for example from [curl](https://curl.se/ca/cacert.pem) site* -#### For other ISPs program has ```--auto``` key to automatically find proper settings +*CA Bundle is a file that contains root and intermediate SSL certificates. Required for DoH and autoconfig to work. You +can get it for example from the [curl](https://curl.se/ca/cacert.pem) website* + +#### For other ISPs, `--auto` will automatically find proper settings ## Running + ### HTTP mode (default) + This mode is good for PC or any other device which will only use the proxy for itself. -Run executable with options either from autoconfig or from one of the suggested profiles. The program will tell IP and port on which the proxy server is running. 0.0.0.0 IP means any of IPs this machine has. +Run executable with options either from autoconfig or from one of the suggested profiles. The program will tell IP and +port on which the proxy server is running. 0.0.0.0 IP means any of IPs this machine has. Set this proxy in browser or system settings ### Transparent mode + This mode is good for router which will use the proxy for the entire local network. -Run executable with ```--mode transparent``` and append options either from autoconfig or from one of the suggested profiles. The program will tell IP and port on which the proxy server is running. 0.0.0.0 IP means any of IPs this machine has. +Run executable with `--mode transparent` and append options either from autoconfig or from one of the suggested +profiles. The program will tell IP and port on which the proxy server is running. 0.0.0.0 IP means any of IPs this +machine has. + +#### If proxy running on router -#### If proxy running on router: ##### 1. Enable IP forwarding -``` + +```bash sysctl -w net.ipv4.ip_forward=1 ``` + ##### 2. Disable ICMP redirects -``` + +```bash sysctl -w net.ipv4.conf.all.send_redirects=0 ``` -##### 3. Enter something like the following ```iptables``` rules: -``` + +##### 3. Enter something like the following ```iptables``` rules + +```bash iptables -t nat -A PREROUTING -i -p tcp --dport 80 -j REDIRECT --to-port iptables -t nat -A PREROUTING -i -p tcp --dport 443 -j REDIRECT --to-port ``` -#### If proxy running on machine in local network (Raspberry PI for example): -##### 1. On router: -``` +#### If proxy running on machine in local network (Raspberry PI for example) + +##### 1. On router + +```bash iptables -t mangle -A PREROUTING -j ACCEPT -p tcp -m multiport --dports 80,443 -s iptables -t mangle -A PREROUTING -j MARK --set-mark 3 -p tcp -m multiport --dports 80,443 ip rule add fwmark 3 table 2 ip route add default via dev table 2 ``` -##### 2. On proxy machine: + +##### 2. On proxy machine + 1. Enable IP forwarding -``` + +```bash sysctl -w net.ipv4.ip_forward=1 ``` + 2. Disable ICMP redirects -``` + +```bash sysctl -w net.ipv4.conf.all.send_redirects=0 ``` + 3. Enter something like the following ```iptables``` rules: -``` + +```bash iptables -t nat -A PREROUTING -i -p tcp --dport 80 -j REDIRECT --to-port iptables -t nat -A PREROUTING -i -p tcp --dport 443 -j REDIRECT --to-port ``` ## Links -[Telegram chat](https://t.me/DPITunnelOFFICIAL) -[Android Version](https://github.com/nomoresat/DPITunnel-android) -[4PDA](https://4pda.to/forum/index.php?showtopic=1043778) +* [Telegram chat](https://t.me/DPITunnelOFFICIAL) +* [Android Version](https://github.com/nomoresat/DPITunnel-android) +* [4PDA](https://4pda.to/forum/index.php?showtopic=1043778) ## Thanks + * [ValdikSS (GoodbyeDPI)](https://github.com/ValdikSS/GoodbyeDPI) * [nomoresat (DPITunnel)](https://github.com/nomoresat/DPITunnel) ## Dependencies + * [RawSocket](https://github.com/chkpk/RawSocket) * [cpp-httplib](https://github.com/yhirose/cpp-httplib) * [dnslib](https://github.com/mnezerka/dnslib) diff --git a/autoconf.cpp b/autoconf.cpp index c05dfc6..8e5c1cf 100644 --- a/autoconf.cpp +++ b/autoconf.cpp @@ -223,7 +223,7 @@ int check_http_response(int socket, std::string host, std::string ip, int port, if (last_char == 0) return -1; - // Count factors indicating that packet was send by DPI + // Count factors indicating that packet was sent by DPI unsigned short factors = 0; // Check time if (receive_time < connect_time * 2 / 3) @@ -540,11 +540,11 @@ int run_autoconf() { fakes_ttl--; // Iterate through all combinations - const std::vector zero_attacks = {DESYNC_ZERO_NONE, DESYNC_ZERO_FAKE, + const std::vector zero_attacks = {DESYNC_ZERO_NONE, DESYNC_ZERO_FAKE, DESYNC_ZERO_RST, DESYNC_ZERO_RSTACK}; - const std::vector first_attacks = {DESYNC_FIRST_DISORDER_FAKE, + const std::vector first_attacks = {DESYNC_FIRST_DISORDER_FAKE, DESYNC_FIRST_SPLIT_FAKE}; - const std::vector fake_types = {"ttl", "wrong-seq"}; + const std::vector fake_types = {"ttl", "wrong-seq"}; const std::vector win_size_scales = {false, true}; unsigned int comb_all = zero_attacks.size() * first_attacks.size() * fake_types.size() * win_size_scales.size(); diff --git a/cmake/Modules/FindLibNL.cmake b/cmake/Modules/FindLibNL.cmake index 81beec6..f1cbddd 100644 --- a/cmake/Modules/FindLibNL.cmake +++ b/cmake/Modules/FindLibNL.cmake @@ -1,16 +1,16 @@ message("Searching for Linux netlink library") if (LibNL_FIND_REQUIRED) - message(" (required)") + message(" (required)") else (LibNL_FIND_REQUIRED) - message(" (not required)") + message(" (not required)") endif (LibNL_FIND_REQUIRED) find_path(LibNL_INCLUDE_DIR netlink/netlink.h - /usr/include - /usr/include/libnl3 - /usr/local/include - /usr/local/include/libnl3 + /usr/include + /usr/include/libnl3 + /usr/local/include + /usr/local/include/libnl3 ) find_library(LibNL_LIBRARY NAMES nl nl-3) @@ -19,21 +19,21 @@ find_library(LibNL_NETFILTER_LIBRARY NAMES nl-nf nl-nf-3) find_library(LibNL_GENL_LIBRARY NAMES nl-genl nl-genl-3) if (LibNL_INCLUDE_DIR AND LibNL_LIBRARY) - set(LibNL_FOUND TRUE) + set(LibNL_FOUND TRUE) endif (LibNL_INCLUDE_DIR AND LibNL_LIBRARY) if (LibNL_FOUND) - if (NOT LibNL_FIND_QUIETLY) - set(LibNL_LIBRARIES ${LibNL_LIBRARY} ${LibNL_ROUTE_LIBRARY} ${LibNL_NETFILTER_LIBRARY} ${LibNL_GENL_LIBRARY}) + if (NOT LibNL_FIND_QUIETLY) + set(LibNL_LIBRARIES ${LibNL_LIBRARY} ${LibNL_ROUTE_LIBRARY} ${LibNL_NETFILTER_LIBRARY} ${LibNL_GENL_LIBRARY}) message("Found netlink libraries: ${LibNL_LIBRARIES}") message("Found netlink includes: ${LibNL_INCLUDE_DIR}") - endif (NOT LibNL_FIND_QUIETLY) + endif (NOT LibNL_FIND_QUIETLY) ELSE (LibNL_FOUND) - if (LibNL_FIND_REQUIRED) - message("Netlink version 3 development packages cannot be found.") - message("In Debian/Ubuntu, they may be called:") - message("libnl-3-dev libnl-genl-3dev libnl-nf-3-dev libnl-route-3-dev") - message(FATAL_ERROR "Could not find netlink library.") - endif (LibNL_FIND_REQUIRED) + if (LibNL_FIND_REQUIRED) + message("Netlink version 3 development packages cannot be found.") + message("In Debian/Ubuntu, they may be called:") + message("libnl-3-dev libnl-genl-3dev libnl-nf-3-dev libnl-route-3-dev") + message(FATAL_ERROR "Could not find netlink library.") + endif (LibNL_FIND_REQUIRED) endif (LibNL_FOUND) diff --git a/desync.cpp b/desync.cpp index 1195ec7..a2244cb 100644 --- a/desync.cpp +++ b/desync.cpp @@ -123,7 +123,7 @@ int sniff_ack_packet(std::string *packet, std::string ip_srv, int port_srv, int port_src_recv = ntohs(tcp_h->source); // Get dest port (client port) int port_dst_recv = ntohs(tcp_h->dest); - // Compare received IP/port and IP/port we waiting for + // Compare received IP/port and IP/port we're waiting for if (ip_h->saddr == ip_srv_sockaddr.sin_addr.s_addr && port_srv == port_src_recv && port_local == port_dst_recv) { *packet = buffer; @@ -228,7 +228,7 @@ int sniff_handshake_packet(std::string *packet, std::string ip_srv, int port_src_recv = ntohs(tcp_h->source); // Get dest port (client port) int port_dst_recv = ntohs(tcp_h->dest); - // Compare received IP/port and IP/port we waiting for + // Compare received IP/port and IP/port we're waiting for if (ip_h->saddr == ip_srv_sockaddr.sin_addr.s_addr && port_srv == port_src_recv) { if (!is_searched) diff --git a/dns.cpp b/dns.cpp index c4dcd55..be14f64 100644 --- a/dns.cpp +++ b/dns.cpp @@ -172,7 +172,7 @@ int resolve_host_over_udp(const std::string &host, std::string &ip) { try { dns_msg_resp.decode(response.c_str(), bytes_read); } catch (dns::Exception &e) { - std::cerr << "Exception occured while parsing DNS response: " << e.what() + std::cerr << "Exception occurred while parsing DNS response: " << e.what() << std::endl; close(sock); return -1; @@ -281,7 +281,7 @@ int resolve_host_over_doh(const std::string &host, std::string &ip) { try { dns_msg_resp.decode(response_string.c_str(), response_string.size()); } catch (dns::Exception &e) { - std::cerr << "Exception occured while parsing DNS response: " << e.what() << std::endl; + std::cerr << "Exception occurred while parsing DNS response: " << e.what() << std::endl; return -1; } diff --git a/include/profiles.h b/include/profiles.h index e16fdec..37150c4 100644 --- a/include/profiles.h +++ b/include/profiles.h @@ -4,6 +4,6 @@ void add_profile(std::string name, Profile_s profile); int change_profile(const std::string &iface, const std::string &wifi_ap, - std::string *choosen_profile_name = NULL); + std::string *chosen_profile_name = NULL); #endif //PROFILES_H diff --git a/netiface.cpp b/netiface.cpp index 5c00a1d..87da733 100644 --- a/netiface.cpp +++ b/netiface.cpp @@ -72,7 +72,7 @@ void route_monitor_thread() { return; } - // Make sokcet non-blocking + // Make socket non-blocking if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK) == -1) { std::cerr << "Failed to make netlink socket non-blocking. Errno: " << std::strerror(errno) << std::endl; diff --git a/packet.cpp b/packet.cpp index a0d4394..ad6624b 100644 --- a/packet.cpp +++ b/packet.cpp @@ -75,7 +75,7 @@ int parse_request(const std::string &request, std::string &method, std::string & std::string found_url; if (is_proxy) { - // Extract hostname an port if exists + // Extract hostname and port if exists std::string regex_string = "[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[-a-z0-9]{1,16}(:[0-9]{1,5})?"; std::regex url_find_regex(regex_string); std::smatch match; diff --git a/profiles.cpp b/profiles.cpp index b140381..2d96f6d 100644 --- a/profiles.cpp +++ b/profiles.cpp @@ -15,7 +15,7 @@ void add_profile(std::string name, Profile_s profile) { } int change_profile(const std::string &iface, const std::string &wifi_ap, - std::string *choosen_profile_name /*= NULL*/) { + std::string *chosen_profile_name /*= NULL*/) { if (Profiles.empty()) return 0; @@ -38,8 +38,8 @@ int change_profile(const std::string &iface, const std::string &wifi_ap, } } - if (choosen_profile_name != NULL) - *choosen_profile_name = search->first; + if (chosen_profile_name != NULL) + *chosen_profile_name = search->first; return 0; }