Skip to content

Commit

Permalink
dht integration
Browse files Browse the repository at this point in the history
  • Loading branch information
novemus committed Aug 3, 2024
1 parent 832ccb7 commit 64baf91
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 64 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## 3.1.0 (Aug 1, 2024)

- The ability to use DHT as the rendezvous.

## 3.0.1 (May 31, 2024)

- Build with default boost library.
Expand Down
68 changes: 52 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
message("***** plexus *****")

cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)

project(plexus)
project(${PROJECT_NAME} VERSION 3.0)
project(${PROJECT_NAME} VERSION 3.1)

add_subdirectory(wormhole)

Expand All @@ -23,6 +23,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_STATIC_LIBRARY_PREFIX "lib")
set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE)
add_definitions(
-D_CRT_NO_VA_START_VALIDATION
-D_CRT_SECURE_NO_WARNINGS
Expand Down Expand Up @@ -56,6 +57,8 @@ endif()

string(REGEX REPLACE "[^/\\]+" ".." PLEXUS_INSTALL_CMAKEDIR_REVERSE ${PLEXUS_INSTALL_CMAKEDIR})

include_directories(wormhole)

set(Boost_USE_STATIC_LIBS ON)

if(BUILD_TESTING)
Expand All @@ -70,7 +73,6 @@ message("* Boost Librariy Dirs: ${Boost_LIBRARY_DIRS}")
message("* Boost Libraries: ${Boost_LIBRARIES}")

include_directories(${Boost_INCLUDE_DIRS})
include_directories(wormhole)
link_directories(${Boost_LIBRARY_DIRS})

find_package(OpenSSL REQUIRED)
Expand All @@ -79,17 +81,49 @@ message("* OpenSSL Version: ${OPENSSL_VERSION}")
message("* OpenSSL Include Dir: ${OPENSSL_INCLUDE_DIR}")
message("* OpenSSL Libraries: ${OPENSSL_LIBRARIES}")

include_directories(${OPENSSL_INCLUDE_DIR})

find_package(PkgConfig REQUIRED)
# pkg_search_module(jsoncpp REQUIRED IMPORTED_TARGET jsoncpp)
# pkg_search_module(nettle REQUIRED IMPORTED_TARGET nettle)
# pkg_search_module(gnutls REQUIRED IMPORTED_TARGET gnutls)
pkg_search_module(opendht REQUIRED IMPORTED_TARGET opendht)

include_directories(${OPENSSL_INCLUDE_DIR})
pkg_search_module(opendht REQUIRED IMPORTED_TARGET opendht)
message("* opendht Include Dir: ${opendht_INCLUDEDIR}")
message("* opendht Lib Dir: ${opendht_LIBDIR}")
include_directories(${opendht_INCLUDE_DIR})
link_directories(${opendht_LIBDIR})

pkg_search_module(JsonCpp REQUIRED IMPORTED_TARGET jsoncpp)
message("* JsonCpp Include Dir: ${JsonCpp_INCLUDEDIR}")
message("* JsonCpp Lib Dir: ${JsonCpp_LIBDIR}")
include_directories(${JsonCpp_INCLUDE_DIR})
link_directories(${JsonCpp_LIBDIR})

pkg_search_module(libargon2 REQUIRED IMPORTED_TARGET libargon2)
message("* libargon2 Include Dir: ${libargon2_INCLUDEDIR}")
message("* libargon2 Lib Dir: ${libargon2_LIBDIR}")
include_directories(${libargon2_INCLUDE_DIR})
link_directories(${libargon2_LIBDIR})

pkg_search_module(fmt REQUIRED IMPORTED_TARGET fmt)
message("* fmt Include Dir: ${fmt_INCLUDEDIR}")
message("* fmt Lib Dir: ${fmt_LIBDIR}")
include_directories(${fmt_INCLUDE_DIR})
link_directories(${fmt_LIBDIR})

pkg_search_module(GnuTLS REQUIRED IMPORTED_TARGET gnutls)
message("* GnuTLS Include Dir: ${GnuTLS_INCLUDEDIR}")
message("* GnuTLS Lib Dir: ${GnuTLS_LIBDIR}")
include_directories(${GnuTLS_INCLUDE_DIR})
link_directories(${GnuTLS_LIBDIR})

pkg_search_module(nettle REQUIRED IMPORTED_TARGET nettle)
message("* nettle Include Dir: ${nettle_INCLUDEDIR}")
message("* nettle Lib Dir: ${nettle_LIBDIR}")
include_directories(${nettle_INCLUDE_DIR})
link_directories(${nettle_LIBDIR})

add_library(${PLEXUS_SHARED} SHARED utils.cpp exec.cpp smime.cpp udp.cpp tcp.cpp email.cpp dht.cpp stun.cpp binder.cpp plexus.cpp)
target_link_libraries(${PLEXUS_SHARED} ${WORMHOLE_SHARED} ${TUBUS_SHARED} OpenSSL::Crypto OpenSSL::SSL opendht gnutls nettle jsoncpp http_parser argon2)
target_compile_definitions(${PLEXUS_SHARED} PRIVATE PLEXUS_EXPORTS)
target_link_libraries(${PLEXUS_SHARED} PRIVATE ${TUBUS_SHARED} ${WORMHOLE_SHARED} Boost::coroutine OpenSSL::SSL OpenSSL::Crypto PkgConfig::opendht PkgConfig::fmt PkgConfig::libargon2 PkgConfig::GnuTLS PkgConfig::nettle PkgConfig::JsonCpp)
target_compile_definitions(${PLEXUS_SHARED} PRIVATE PLEXUS_EXPORTS OPENDHT_STATIC)
set_target_properties(${PLEXUS_SHARED} PROPERTIES DEBUG_POSTFIX "d" IMPORT_PREFIX "lib")
set_target_properties(${PLEXUS_SHARED} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})

Expand All @@ -98,15 +132,16 @@ set_target_properties(${PLEXUS_STATIC} PROPERTIES DEBUG_POSTFIX "d")
set_target_properties(${PLEXUS_STATIC} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})

add_executable(${PROJECT_NAME} main.cpp $<TARGET_OBJECTS:${PLEXUS_SHARED}>)
target_link_libraries(${PROJECT_NAME} ${TUBUS_STATIC} ${WORMHOLE_STATIC} OpenSSL::Crypto OpenSSL::SSL opendht gnutls nettle jsoncpp http_parser argon2)
target_link_libraries(${PROJECT_NAME} PRIVATE ${TUBUS_STATIC} ${WORMHOLE_STATIC} Boost::coroutine Boost::program_options OpenSSL::SSL OpenSSL::Crypto PkgConfig::opendht PkgConfig::fmt PkgConfig::libargon2 PkgConfig::GnuTLS PkgConfig::nettle PkgConfig::JsonCpp)
target_compile_definitions(${PROJECT_NAME} PRIVATE OPENDHT_STATIC)
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -fPIC -fvisibility=hidden")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${PROJECT_NAME} Threads::Threads Boost::system Boost::coroutine Boost::program_options)
target_link_libraries(${PLEXUS_SHARED} Boost::system Boost::coroutine)
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads Boost::system)
target_link_libraries(${PLEXUS_SHARED} PRIVATE Boost::system)
endif()

if(APPLE)
Expand All @@ -116,7 +151,7 @@ if(APPLE)
cmake_policy(POP)
get_filename_component(ICU_LIBDATA_DIR "${ICU_DATA_LIBRARY}" DIRECTORY)
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-L${ICU_LIBDATA_DIR}")
set_target_properties(${PLEXUS_SHARED} PROPERTIES LINK_FLAGS "-L${ICU_LIBDATA_DIR}")
set_target_properties(${PLEXUS_SHARED} PROPERTIES LINK_FLAGS "-L${ICU_LIBDATA_DIR}")
endif()

# install executable
Expand Down Expand Up @@ -159,11 +194,12 @@ if(BUILD_TESTING)
tests/smime_tests.cpp
tests/exec_tests.cpp
tests/plexus_tests.cpp)
target_link_libraries(${PLEXUS_UT} ${PLEXUS_STATIC} ${WORMHOLE_STATIC} ${TUBUS_STATIC} OpenSSL::Crypto OpenSSL::SSL opendht gnutls nettle jsoncpp http_parser argon2)
target_link_libraries(${PLEXUS_UT} PRIVATE ${PLEXUS_STATIC} ${WORMHOLE_STATIC} ${TUBUS_STATIC} Boost::coroutine Boost::program_options Boost::unit_test_framework OpenSSL::SSL OpenSSL::Crypto PkgConfig::opendht PkgConfig::fmt PkgConfig::libargon2 PkgConfig::GnuTLS PkgConfig::nettle PkgConfig::JsonCpp)
target_compile_definitions(${PLEXUS_UT} PRIVATE OPENDHT_STATIC)
set_target_properties(${PLEXUS_UT} PROPERTIES DEBUG_POSTFIX "d")

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_link_libraries(${PLEXUS_UT} Threads::Threads Boost::system Boost::coroutine Boost::program_options Boost::unit_test_framework)
target_link_libraries(${PLEXUS_UT} PRIVATE Threads::Threads Boost::system)
endif()

if(APPLE)
Expand Down
46 changes: 24 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,44 @@
# README

The [plexus](https://github.com/novemus/plexus) tool is designed to make the possibility of establishing a direct network connection between applications running on machines located behind *NAT*s. To do this `plexus` implements the well-known *UDP hole punching* technique using the *STUN*. An email service is used to exchange public addresses between app instances on the local and remote machines. For success, it is necessary that *NAT*s on both sides implement independent mapping policy of internal addresses to public ones. That is, the public address and port assigned by the *NAT* should not be changed when the destination address/port of the outgoing packet is changed, while the local address/port of the outgoing packet remains unchanged. In addition, you will need an accessible *STUN* server and email accounts for each side. It is possible to use one email account for both sides.
The [plexus](https://github.com/novemus/plexus) tool is designed to make the possibility of establishing a direct network connection between applications running on machines located behind *NAT*s. To do this `plexus` implements the well-known *UDP hole punching* technique using the *STUN*. You can use a `DHT` network or `email` service as a rendezvous to exchange public addresses between local and remote app instances. For success, it is necessary that *NAT*s on both sides implement independent mapping policy of internal addresses to public ones. That is, the public address and port assigned by the *NAT* should not be changed when the destination address/port of the outgoing packet is changed, while the source address/port of the outgoing packet remains unchanged. In addition, you will need an accessible *STUN* server and email accounts for each side if you want to use `email` as the rendezvous. It is possible to use one email account for both sides.

## Build

You can download [prebuild packages](https://github.com/novemus/plexus/releases) for Debian and Windows platforms.

The project depends on `boost` and `openssl` libraries. Clone repository and run make command.
The project depends on [boost](https://github.com/boostorg/boost), [openssl](https://github.com/openssl/openssl) and [opendht](https://github.com/savoirfairelinux/opendht) libraries. Clone the repository, then configure and build project.

```console
$ cd ~
$ git clone --recurse-submodules https://github.com/novemus/plexus.git
$ cd ~/plexus
$ cmake -B ./build [-DBOOST_ROOT=...] [-DOPENSSL_ROOT_DIR=...]
$ [PKG_CONFIG_PATH=/path/to/opendht/pkgconfig] cmake -B ./build [-DBOOST_ROOT=...] [-DOPENSSL_ROOT_DIR=...]
$ cmake --build ./build --target plexus [plexus_shared] [plexus_static] [plexus_ut]
$ cmake --build ./build --target install
```

To build libraries, specify the *plexus_static* and *plexus_shared* targets.
To build the libraries, specify the *plexus_static* and *plexus_shared* targets.

## Using

To run the example below you need to install *openvpn*. Launch following commands with your arguments on each machines. Script *exec.sh* will try to establish point-to-point *VPN* connection.
Create an application repository and specify the path to the host directory according to the scheme `apprepo/owner@mailer.com/pin`. You must place there the X509 *cert.crt* certificate and the *private.key* key of the host. Likewise, make the directory for the peer and place there its *cert.crt* certificate. Make the same on the peer machine. The intermediate directory `owner@mailer.com` can be named as you want if you use the `DHT` rendezvous, but for the `email` case it must have the name of the appropriate email address. So for compatibility, it is recommended to always use the email address.

Command for remote machine:
To run the example below you need to install the *openvpn*. The *exec.sh* script will try to establish point-to-point *VPN* connection.

Command for the accepting side:
```console
$ plexus --accept --app-id=appname --email-smtps=smtp.mailer.com[:xxxx] --email-imaps=imap.mailer.com[:xxxx] --email-login=login --email-password=password --host-info=host@mailer.com/hostname --peer-info=peer@mailer.com/peername --stun-server=stun.someserver.com[:xxxx] --stun-client=xxx.xxx.xxx.xxx[:xxxx] --exec-command=~/plexus/tests/exec.sh
$ plexus --app-id=appname --app-repo=/path/to/apprepo --accept --dht-bootstrap=bootstrap.jami.net:4222 --host-info=host@mailer.com/hostid --peer-info=peer@mailer.com/peerid --stun-server=stun.someserver.com[:xxxx] --exec-command=~/plexus/tests/exec.sh
```

`--accept` key tells the app to cyclically accept initiations from other side. It must only be set for one side. If you want to accept several peers, create application repository and specify the path for each peer as `apprepo/peer@mailer.com/peername`. To use email encryption, you must place the X509 *cert.crt* peer certificates and, optionally, their CA *ca.crt* certificates in the appropriate folders. You must also make the same for the local host and additionally place its *private.key* key. The same must be done on every peer machine. Specify application repository with `--app-repo` argument.

Some *NAT*s may drop mappings when receiving an incoming packet that does not meet the filtering policy. This package may be a punching package sent by `plexus` towards the peer. In this case, it is impossible to punch the *passage* between the machines. To avoid such situations, `plexus` sets a small *ttl* to the punching packet, by default 7. In general, this is enough for the packet to go beyond the host *NAT* to punch it, but not reach the peer *NAT* to not drop peer mapping. If necessary, you can set a more appropriate *ttl* using the `--punch-hops` argument, defining a suitable value by some routing utility. This only makes sense for the *accepting* side.

Command for local machine:
Command for the inviting side:
```console
$ plexus --app-id=appname --email-smtps=smtp.mailer.com[:xxxx] --email-imaps=imap.mailer.com[:xxxx] --email-login=login --email-password=password --host-info=host@mailer.com/hostname --peer-info=peer@mailer.com/peername --stun-server=stun.someserver.com[:xxxx] --stun-client=xxx.xxx.xxx.xxx[:xxxx] --exec-command=~/plexus/tests/exec.sh
$ plexus --app-id=appname --app-repo=/path/to/apprepo --dht-bootstrap=bootstrap.jami.net:4222 --host-info=host@mailer.com/hostid --peer-info=peer@mailer.com/peerid --stun-server=stun.someserver.com[:xxxx] --exec-command=~/plexus/tests/exec.sh
```

The `--app-id` key determines the target application. The `--host-info` argument points to the local application identity and the `--peer-info` points to the remote one. The `--app-repo` key is used to specify the application repository. The `--accept` key tells the app to cyclically accept invitations from the remotes. It must only be set for one side. If you want to accept many peers you should just omit the `--peer-info` argument. In this case, every peer is contained in the repository will be accepted.

Some *NAT*s may drop mapping when receiving an incoming packet that does not meet the filtering policy. This package may be a punching package sent by `plexus` towards the peer. In this case, it is impossible to punch the *passage* between the machines. To avoid such situations, `plexus` sets a small *ttl* to the punching packet, by default 7. In general, this is enough for the packet to go beyond the host *NAT* to punch it, but not to reach the peer *NAT* and not to drop its peer mapping. If necessary, you can set a more appropriate *ttl* using the `--punch-hops` argument, determining the suitable value by some routing utility. This only makes sense for the *accepting* side.

As soon as both `plexus` instanses make the *passage* to each other the command specified by `--exec-command` will be started. You can pass your arguments to the executable by `--exec-args` argument with the following wildcards:

`%innerip%` - local address specified by `--stun-client` argument
Expand All @@ -47,21 +49,21 @@ As soon as both `plexus` instanses make the *passage* to each other the command

`%outerport%` - port issued by the NAT

`%peerip%` - public address of the peer received by email
`%peerip%` - public address of the peer received by the rendezvous

`%peerport%` - port of the peer received by email
`%peerport%` - port of the peer received by the rendezvous

`%hostpin%` - name of the host
`%hostmail%` - owner of the host, first part of the `--host-info` argument

`%peerpin%` - name of the peer
`%peermail%` - owner of the peer, first part of the `--peer-info` argument

`%hostmail%` - email of the host
`%hostpin%` - id of the host, second part of the `--host-info` argument

`%peermail%` - email of the peer
`%peerpin%` - id of the peer, second part of the `--peer-info` argument

`%secret%` - shared 64-bit key used for the handshake procedure

To learn about additional parameters run tool with `--help` argument.
To learn about additional parameters run the tool with the `--help` key.

## Extensions and Library

Expand All @@ -77,12 +79,12 @@ Local machine:
--exec-command=wormhole --exec-args="--purpose=import --service=127.0.0.1:2222 --gateway=%innerip%:%innerport% --faraway=%peerip%:%peerport%" --exec-log=import.ssh.log
```

Then connect to the remote *ssh* via the local port:
Then connect to the remote *ssh* via the local mapping:
```console
$ ssh -p 2222 127.0.0.1
```

The `plexus` library API is described in the [plexus.h](https://github.com/novemus/plexus/blob/master/plexus.h) header and provides the same functionality with additional UDP streaming capability, so you will need the [tubus](https://github.com/novemus/tubus) UDP library.
The `plexus` library API is described in the [plexus.h](https://github.com/novemus/plexus/blob/master/plexus.h) header and provides the same functionality with the additional UDP streaming capability, so you will need the [tubus](https://github.com/novemus/tubus) UDP library.

## Bugs and improvements

Expand Down
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
plexus (3.1-1+deb12u3) unstable; urgency=low

* - The ability to use DHT as the rendezvous.

-- Novemus Band <nineletters@mail.ru> Thu, 1 Aug 2024 21:00:00 +0300

plexus (3.0-2+deb12u3) unstable; urgency=low

* Build with default boost library.
Expand Down
6 changes: 3 additions & 3 deletions debian/libplexus-dev.install
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
usr/include
usr/lib/*/*/*.a
usr/lib/*/cmake/*/*.cmake
opt/plexus/*/include
opt/plexus/*/lib/*/*.a
opt/plexus/*/lib/*/cmake/*.cmake
2 changes: 1 addition & 1 deletion debian/libplexus.install
Original file line number Diff line number Diff line change
@@ -1 +1 @@
usr/lib/*/*/*.so
opt/plexus/*/lib/*/*.so
2 changes: 1 addition & 1 deletion debian/plexus.install
Original file line number Diff line number Diff line change
@@ -1 +1 @@
usr/bin
opt/plexus/*/bin
1 change: 1 addition & 0 deletions debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
override_dh_auto_configure:
dh_auto_configure -- \
-DCMAKE_LIBRARY_ARCHITECTURE="$(DEB_TARGET_MULTIARCH)" \
-DCMAKE_INSTALL_PREFIX=/opt \
-DTUBUS_SKIP_INSTALL=ON \
-DWORMHOLE_SKIP_INSTALL=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo
Loading

0 comments on commit 64baf91

Please sign in to comment.