diff --git a/extras/packaging/gnu-linux/debian/postinst b/extras/packaging/gnu-linux/debian/postinst
index 33a7e8e11b88d549104ff034381766251da2a938..39ad146ec20fa8eca45a8232e9d49edf1dceb9ee 100644
--- a/extras/packaging/gnu-linux/debian/postinst
+++ b/extras/packaging/gnu-linux/debian/postinst
@@ -68,6 +68,15 @@ configure_yaml() {
             echo "# When anonymous is set to false, the server allows only connection which are issued by the same CA as the server"
             echo "anonymous: false"
             echo ""
+            echo "# List of authorized services"
+            echo "# Each service is defined by an IP and a port"
+            echo "authorized_services:"
+            echo "  - ip: \"127.0.0.1\""
+            echo "    port: 22"
+            echo "  # - ip: \"127.0.0.1\""
+            echo "  #   port: 80"
+            echo "  # - ip: \"127.0.0.1\""
+            echo "  #   port: 443"
             echo ""
         } > /etc/dhtnet/dnc.yaml
     fi
diff --git a/tools/dhtnet_crtmgr/main.cpp b/tools/dhtnet_crtmgr/main.cpp
index 968a9364473bc181e2a6ecbdd828e52716aebbdf..4ad8dfe830ca2c7d74825a1938f7170f1567b391 100644
--- a/tools/dhtnet_crtmgr/main.cpp
+++ b/tools/dhtnet_crtmgr/main.cpp
@@ -135,6 +135,17 @@ int create_yaml_config(std::filesystem::path file, std::filesystem::path certifi
             yaml_file << "\n# When anonymous is set to true, the server accepts any connection without checking CA\n";
             yaml_file << "# When anonymous is set to false, the server allows only connection which are issued by the same CA as the server\n";
             yaml_file << "anonymous: false\n";
+
+            yaml_file << "\n# List of authorized services\n";
+            yaml_file << "# Each service is defined by an IP and a port\n";
+            yaml_file << "# If no authorized services are defined, the server will accept any connection.\n";
+            yaml_file << "authorized_services:\n";
+            yaml_file << "  - ip: \"127.0.0.1\"\n";
+            yaml_file << "    port: 22\n";
+            yaml_file << "  # - ip: \"127.0.0.1\"\n";
+            yaml_file << "  #   port: 80\n";
+            yaml_file << "  # - ip: \"127.0.0.1\"\n";
+            yaml_file << "  #   port: 443\n";
         }
         yaml_file.close();
         fmt::print("Configuration file created in {}\n", file);
diff --git a/tools/dnc/dnc.cpp b/tools/dnc/dnc.cpp
index 764945ccfe6dbf070a68c9334fc42120c2407991..86bb159385c3d3126ce0b362f1dac8831d7322e9 100644
--- a/tools/dnc/dnc.cpp
+++ b/tools/dnc/dnc.cpp
@@ -60,7 +60,8 @@ Dnc::Dnc(dht::crypto::Identity identity,
          const std::string& turn_pass,
          const std::string& turn_realm,
          const bool anonymous,
-         const bool verbose)
+         const bool verbose,
+         const std::map<std::string, std::vector<int>> authorized_services)
     :logger(verbose ? dht::log::getStdLogger() : nullptr),
     ioContext(std::make_shared<asio::io_context>()),
     iceFactory(std::make_shared<IceTransportFactory>(logger))
@@ -104,9 +105,40 @@ Dnc::Dnc(dht::crypto::Identity identity,
     std::unique_lock lk {mtx};
 
     connectionManager->onChannelRequest(
-        [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string& name) {
+        [authorized_services, this](const std::shared_ptr<dht::crypto::Certificate>&, const std::string& name) {
             // handle channel request
-            fmt::print("Channel request received: {}\n", name);
+            if (authorized_services.empty()) {
+                // Accept all connections if no authorized services are provided
+                return true;
+            }
+            // parse channel name to get the ip address and port: nc://<ip>:<port>
+            auto parsedName = parseName(name);
+            const std::string &ip = parsedName.first;
+            int port = 0;
+            try {
+                port = std::stoi(parsedName.second);
+            }
+            catch (std::exception const &err) {
+                fmt::print(stderr, "Rejecting connection: port '{}' is not a valid number", parsedName.second);
+                return false;
+            }
+
+            // Check if the IP is authorized
+            auto it = authorized_services.find(ip);
+            if (it == authorized_services.end()) {
+                // Reject the connection if the ip is not authorized
+                fmt::print("Rejecting connection to {}:{}", ip, port);
+                return false;
+            }
+
+            // Check if the port is authorized
+            const auto &ports = it->second;
+            if (std::find(ports.begin(), ports.end(), port) == ports.end()) {
+                // Reject the connection if the port is not authorized
+                fmt::print("Rejecting connection to {}:{}", ip, port);
+                return false;
+            }
+            fmt::print("Accepting connection to {}:{}", ip, port);
             return true;
         });
 
@@ -175,10 +207,11 @@ Dnc::Dnc(dht::crypto::Identity identity,
          const std::string& turn_pass,
          const std::string& turn_realm,
          const bool verbose)
-    : Dnc(identity, bootstrap,turn_host,turn_user,turn_pass, turn_realm, true, verbose)
+    : Dnc(identity, bootstrap,turn_host,turn_user,turn_pass, turn_realm, true, verbose, {})
 {
     std::condition_variable cv;
     auto name = fmt::format("nc://{:s}:{:d}", remote_host, remote_port);
+    fmt::print("Requesting socket: %s\n", name.c_str());
     connectionManager->connectDevice(
         peer_id, name, [&](std::shared_ptr<ChannelSocket> socket, const dht::InfoHash&) {
             if (socket) {
diff --git a/tools/dnc/dnc.h b/tools/dnc/dnc.h
index 665d2a0af5154b51d033536136e1b9d87d5a10a2..6e5537dfa63c602423c0e4c4606845284842332d 100644
--- a/tools/dnc/dnc.h
+++ b/tools/dnc/dnc.h
@@ -40,7 +40,8 @@ public:
         const std::string& turn_pass,
         const std::string& turn_realm,
         const bool anonymous,
-        const bool verbose);
+        const bool verbose,
+        const std::map<std::string, std::vector<int>> authorized_services);
     // Build a client
     Dnc(
         dht::crypto::Identity identity,
diff --git a/tools/dnc/dnc.yaml b/tools/dnc/dnc.yaml
index 412ab08e92874778399d8b1b781440988f67e33f..f1b06ea28ea825d090bce3092509864c6e7ae5c5 100644
--- a/tools/dnc/dnc.yaml
+++ b/tools/dnc/dnc.yaml
@@ -39,3 +39,13 @@ port: 22
 # When anonymous is set to false, the server allows only connection which are issued by the same CA as the server
 anonymous: false
 
+# List of authorized services
+# Each service is defined by an IP and a port
+# If no authorized services are defined, the server will accept any connection.
+authorized_services:
+  - ip: "127.0.0.1"
+    port: 22
+  # - ip: "127.0.0.1"
+  #   port: 80
+  # - ip: "127.0.0.1"
+  #   port: 443
diff --git a/tools/dnc/main.cpp b/tools/dnc/main.cpp
index e8a89e9781b48d680235a72ec9c9f3e62bfd4782..cf989457e92796412df98704426549c90e319ec5 100644
--- a/tools/dnc/main.cpp
+++ b/tools/dnc/main.cpp
@@ -50,6 +50,7 @@ struct dhtnc_params
     std::string configuration {};
     bool anonymous_cnx {false};
     bool verbose {false};
+    std::map<std::string, std::vector<int>> authorizedServices {};
 };
 
 static const constexpr struct option long_options[]
@@ -172,7 +173,7 @@ parse_args(int argc, char** argv)
                 params.cert = config["certificate"].as<std::string>();
             }
             if (config["ip"] && params.remote_host.empty()) {
-                params.configuration = config["ip"].as<std::string>();
+                params.remote_host = config["ip"].as<std::string>();
             }
             if (config["port"] && params.remote_port == 0) {
                 params.remote_port = config["port"].as<int>();
@@ -183,6 +184,23 @@ parse_args(int argc, char** argv)
             if (config["verbose"] && !params.verbose) {
                 params.verbose = config["verbose"].as<bool>();
             }
+            if (config["authorized_services"]) {
+                for (auto service : config["authorized_services"]) {
+                    std::string ip = service["ip"].as<std::string>();
+                    int port = 0;
+                    try {
+                        port = service["port"].as<int>();
+                    } catch (YAML::TypedBadConversion<int> e) {
+                        std::cerr << "Error: Invalid port number in configuration file.\n";
+                        exit(EXIT_FAILURE);
+                    }
+                    if (port < 1 || port > 65535 || ip.empty()) {
+                        std::cerr << "Error: Invalid ip or port number in configuration file.\n";
+                        exit(EXIT_FAILURE);
+                    }
+                    params.authorizedServices[ip].push_back(port);
+                }
+            }
         }
     }
     return params;
@@ -253,7 +271,8 @@ main(int argc, char** argv)
                                               params.turn_pass,
                                               params.turn_realm,
                                               params.anonymous_cnx,
-                                              params.verbose);
+                                              params.verbose,
+                                              params.authorizedServices);
     } else {
         dhtnc = std::make_unique<dhtnet::Dnc>(identity,
                                               params.bootstrap,