ipv6 + misc
This commit is contained in:
parent
3b73f82938
commit
1e8fcc4879
@ -1,5 +1,10 @@
|
|||||||
#include "../common/defines.h"
|
#include "../common/defines.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
@ -54,23 +59,47 @@ int main(int argc, char *argv[]) {
|
|||||||
error("Error setting cipher list");
|
error("Error setting cipher list");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a TCP socket
|
// Socket creation will be handled in the connection loop
|
||||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sockfd < 0)
|
if (sockfd < 0)
|
||||||
error("Socket creation failed");
|
error("Socket creation failed");
|
||||||
|
|
||||||
// Set up server address
|
// Set up server address
|
||||||
struct sockaddr_in serv_addr;
|
struct sockaddr_storage serv_addr;
|
||||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||||
serv_addr.sin_family = AF_INET;
|
|
||||||
serv_addr.sin_port = htons(atoi(argv[2]));
|
|
||||||
if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
|
|
||||||
error("Invalid address/address not supported");
|
|
||||||
|
|
||||||
// Connect to server
|
struct addrinfo hints, *res;
|
||||||
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC; // Enable IPv4/IPv6 dual support
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
// Resolve hostname and port together
|
||||||
|
int status = getaddrinfo(argv[1], argv[2], &hints, &res);
|
||||||
|
if (status != 0) {
|
||||||
|
std::cerr << "Resolution failed: " << gai_strerror(status) << "\n";
|
||||||
|
std::exit(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try all addresses until successful connection
|
||||||
|
struct addrinfo *rp;
|
||||||
|
for (rp = res; rp != NULL; rp = rp->ai_next) {
|
||||||
|
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
|
if (sockfd == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
|
||||||
|
break; // Success
|
||||||
|
|
||||||
|
close(sockfd);
|
||||||
|
sockfd = -1;
|
||||||
|
}
|
||||||
|
freeaddrinfo(res); // Free after connection attempts
|
||||||
|
|
||||||
|
if (sockfd == -1) {
|
||||||
|
std::cerr << "Failed to connect to all resolved addresses\n";
|
||||||
|
freeaddrinfo(res);
|
||||||
error("Connection failed");
|
error("Connection failed");
|
||||||
|
}
|
||||||
printf("Connected to %s:%s\n", argv[1], argv[2]);
|
printf("Connected to %s:%s\n", argv[1], argv[2]);
|
||||||
|
|
||||||
// Create an SSL object
|
// Create an SSL object
|
||||||
|
|||||||
@ -1 +1,8 @@
|
|||||||
#define BUFFER_SIZE 1024
|
#ifndef COMMON_DEFINES_H
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
enum { CONNECT, DISCONNECT, MESSAGE, CHALLENGE };
|
||||||
|
#endif
|
||||||
177
relay/main.cpp
177
relay/main.cpp
@ -1,16 +1,20 @@
|
|||||||
#include "../common/defines.h"
|
#include "../common/defines.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
#define PORT 9009
|
#define PORT 9009
|
||||||
|
|
||||||
struct Client {
|
struct Client {
|
||||||
@ -23,29 +27,78 @@ std::mutex clients_mutex;
|
|||||||
|
|
||||||
void handle_client(SSL *ssl, int client_socket) {
|
void handle_client(SSL *ssl, int client_socket) {
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Read data securely using OpenSSL
|
|
||||||
int bytes_read = SSL_read(ssl, buffer, sizeof(buffer));
|
int bytes_read = SSL_read(ssl, buffer, sizeof(buffer));
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
// Check for OpenSSL specific errors
|
|
||||||
int err = SSL_get_error(ssl, bytes_read);
|
int err = SSL_get_error(ssl, bytes_read);
|
||||||
if (err == SSL_ERROR_WANT_READ)
|
if (err == SSL_ERROR_WANT_READ)
|
||||||
continue;
|
continue;
|
||||||
break; // Client disconnected or error occurred
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
json cldata =
|
||||||
|
json::parse(std::string(buffer, static_cast<size_t>(bytes_read)));
|
||||||
|
switch (cldata["type"].get<int>()) {
|
||||||
|
case CONNECT: {
|
||||||
|
json response;
|
||||||
|
std::vector<int> socket_values;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(clients_mutex);
|
||||||
|
for (const Client &client : clients) {
|
||||||
|
if (client.socket != client_socket) {
|
||||||
|
socket_values.push_back(client.socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response["pears"] = socket_values;
|
||||||
|
SSL_write(ssl, response.dump().c_str(),
|
||||||
|
static_cast<int>(response.dump().length()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DISCONNECT:
|
||||||
|
std::cout << "Client disconnected: " << cldata["client_id"].get<int>()
|
||||||
|
<< std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MESSAGE: {
|
||||||
|
std::lock_guard<std::mutex> lock(clients_mutex);
|
||||||
|
for (const int &destination_socket : cldata["destinations"]) {
|
||||||
|
auto it = std::find_if(clients.begin(), clients.end(),
|
||||||
|
[destination_socket](const Client &client) {
|
||||||
|
return client.socket == destination_socket;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != clients.end()) {
|
||||||
|
SSL_write(it->ssl, cldata["message"].get<std::string>().c_str(),
|
||||||
|
static_cast<int>(
|
||||||
|
cldata["message"].get<std::string>().length()));
|
||||||
|
} else {
|
||||||
|
std::cerr << "Client not found: " << destination_socket
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cerr << "Unknown message type" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (const json::parse_error &e) {
|
||||||
|
std::cerr << "JSON parse error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast to all other clients
|
// Broadcast to all other clients
|
||||||
std::lock_guard<std::mutex> lock(clients_mutex);
|
std::lock_guard<std::mutex> lock(clients_mutex);
|
||||||
for (const auto &client : clients) {
|
for (const Client &client : clients) {
|
||||||
if (client.socket != client_socket) {
|
if (client.socket != client_socket) {
|
||||||
// Send data securely using OpenSSL
|
|
||||||
SSL_write(client.ssl, buffer, bytes_read);
|
SSL_write(client.ssl, buffer, bytes_read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up when client disconnects
|
// Cleanup client
|
||||||
std::lock_guard<std::mutex> lock(clients_mutex);
|
std::lock_guard<std::mutex> lock(clients_mutex);
|
||||||
clients.erase(std::remove_if(clients.begin(), clients.end(),
|
clients.erase(std::remove_if(clients.begin(), clients.end(),
|
||||||
[client_socket](const Client &c) {
|
[client_socket](const Client &c) {
|
||||||
@ -53,7 +106,6 @@ void handle_client(SSL *ssl, int client_socket) {
|
|||||||
}),
|
}),
|
||||||
clients.end());
|
clients.end());
|
||||||
|
|
||||||
// Free OpenSSL resources
|
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
close(client_socket);
|
close(client_socket);
|
||||||
}
|
}
|
||||||
@ -64,31 +116,23 @@ int main() {
|
|||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
|
|
||||||
// Create a TLS 1.3 server context
|
// Create TLS 1.3 context
|
||||||
SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
|
SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
|
||||||
if (ctx == NULL) {
|
if (!ctx) {
|
||||||
std::cerr << "Failed to create SSL_CTX" << std::endl;
|
std::cerr << "Failed to create SSL_CTX" << std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set min/max protocol to TLS 1.3
|
// Set TLS 1.3 only
|
||||||
SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
|
SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
|
||||||
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
|
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
|
||||||
|
|
||||||
// Load ML-DSA post-quantum certificates and keys
|
// Load post-quantum certificates
|
||||||
if (SSL_CTX_use_certificate_file(ctx, "certs/mldsa87_entity_cert.pem",
|
if (SSL_CTX_use_certificate_file(ctx, "certs/mldsa87_entity_cert.pem",
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
std::cerr << "Error loading certificate file" << std::endl;
|
std::cerr << "Error loading certificate" << std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
|
|
||||||
std::ifstream file("certs/mldsa87_entity_cert.pem");
|
|
||||||
if (file) {
|
|
||||||
std::cout << "Certificate file exists and is readable" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Cannot access certificate file" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
@ -96,34 +140,24 @@ int main() {
|
|||||||
|
|
||||||
if (SSL_CTX_use_PrivateKey_file(ctx, "certs/mldsa87_entity_key.pem",
|
if (SSL_CTX_use_PrivateKey_file(ctx, "certs/mldsa87_entity_key.pem",
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
std::cerr << "Error loading private key file" << std::endl;
|
std::cerr << "Error loading private key" << std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load CA certificate for client verification
|
// Configure cipher suites
|
||||||
if (SSL_CTX_load_verify_locations(ctx, "certs/mldsa87_root_cert.pem", NULL) !=
|
|
||||||
1) {
|
|
||||||
std::cerr << "Error loading CA certificate" << std::endl;
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
SSL_CTX_free(ctx);
|
|
||||||
EVP_cleanup();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure TLS 1.3 cipher suites
|
|
||||||
if (SSL_CTX_set_ciphersuites(ctx, "TLS_AES_256_GCM_SHA384") != 1) {
|
if (SSL_CTX_set_ciphersuites(ctx, "TLS_AES_256_GCM_SHA384") != 1) {
|
||||||
std::cerr << "Error setting cipher suites" << std::endl;
|
std::cerr << "Error setting ciphers" << std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a TCP socket
|
// Create dual-stack IPv6 socket
|
||||||
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
int server_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
if (server_fd < 0) {
|
if (server_fd < 0) {
|
||||||
std::cerr << "Socket creation failed" << std::endl;
|
std::cerr << "Socket creation failed" << std::endl;
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
@ -131,21 +165,33 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set socket options
|
// Enable dual-stack support
|
||||||
int opt = 1;
|
int opt = 0;
|
||||||
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
if (setsockopt(server_fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) < 0) {
|
||||||
std::cerr << "setsockopt failed" << std::endl;
|
std::cerr << "Dual-stack configuration failed" << std::endl;
|
||||||
close(server_fd);
|
close(server_fd);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind socket to port
|
// Set socket options
|
||||||
sockaddr_in address{};
|
int reuse = 1;
|
||||||
address.sin_family = AF_INET;
|
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) <
|
||||||
address.sin_addr.s_addr = INADDR_ANY;
|
0) {
|
||||||
address.sin_port = htons(PORT);
|
std::cerr << "SO_REUSEADDR failed" << std::endl;
|
||||||
|
close(server_fd);
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
EVP_cleanup();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind socket
|
||||||
|
sockaddr_in6 address{};
|
||||||
|
address.sin6_family = AF_INET6;
|
||||||
|
address.sin6_addr = in6addr_any;
|
||||||
|
address.sin6_port = htons(PORT);
|
||||||
|
|
||||||
if (bind(server_fd, (sockaddr *)&address, sizeof(address)) < 0) {
|
if (bind(server_fd, (sockaddr *)&address, sizeof(address)) < 0) {
|
||||||
std::cerr << "Bind failed" << std::endl;
|
std::cerr << "Bind failed" << std::endl;
|
||||||
close(server_fd);
|
close(server_fd);
|
||||||
@ -163,12 +209,13 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Secure server started on port " << PORT << std::endl;
|
std::cout << "Dual-stack server running on port " << PORT << std::endl;
|
||||||
std::cout << "Using TLS 1.3 with post-quantum cryptography" << std::endl;
|
std::cout << "Using TLS 1.3 with ML-DSA-87 post-quantum algorithm"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
// Accept and handle client connections
|
// Main accept loop
|
||||||
while (true) {
|
while (true) {
|
||||||
sockaddr_in client_addr{};
|
sockaddr_in6 client_addr{};
|
||||||
socklen_t client_len = sizeof(client_addr);
|
socklen_t client_len = sizeof(client_addr);
|
||||||
int client_socket =
|
int client_socket =
|
||||||
accept(server_fd, (sockaddr *)&client_addr, &client_len);
|
accept(server_fd, (sockaddr *)&client_addr, &client_len);
|
||||||
@ -178,48 +225,46 @@ int main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char client_ip[INET_ADDRSTRLEN];
|
// Get client IP
|
||||||
inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, INET_ADDRSTRLEN);
|
char client_ip[INET6_ADDRSTRLEN];
|
||||||
std::cout << "New connection from " << client_ip << std::endl;
|
inet_ntop(AF_INET6, &client_addr.sin6_addr, client_ip, INET6_ADDRSTRLEN);
|
||||||
|
std::cout << "Connection from: " << client_ip << std::endl;
|
||||||
|
|
||||||
// Create a new SSL object for this connection
|
// SSL setup
|
||||||
SSL *ssl = SSL_new(ctx);
|
SSL *ssl = SSL_new(ctx);
|
||||||
if (ssl == NULL) {
|
if (!ssl) {
|
||||||
std::cerr << "SSL_new failed" << std::endl;
|
std::cerr << "SSL_new failed" << std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
close(client_socket);
|
close(client_socket);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Associate the socket with SSL
|
|
||||||
if (SSL_set_fd(ssl, client_socket) != 1) {
|
if (SSL_set_fd(ssl, client_socket) != 1) {
|
||||||
std::cerr << "SSL_set_fd failed" << std::endl;
|
std::cerr << "SSL_set_fd failed" << std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
close(client_socket);
|
close(client_socket);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept the TLS connection
|
// TLS handshake
|
||||||
if (SSL_accept(ssl) != 1) {
|
if (SSL_accept(ssl) != 1) {
|
||||||
std::cerr << "TLS handshake failed: " << SSL_get_error(ssl, 0)
|
std::cerr << "TLS handshake failed: " << SSL_get_error(ssl, 0)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
close(client_socket);
|
close(client_socket);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add client to the list
|
// Add client to list
|
||||||
std::lock_guard<std::mutex> lock(clients_mutex);
|
{
|
||||||
clients.push_back({ssl, client_socket});
|
std::lock_guard<std::mutex> lock(clients_mutex);
|
||||||
|
clients.push_back({ssl, client_socket});
|
||||||
|
}
|
||||||
|
|
||||||
// Create a thread to handle this client
|
// Start client thread
|
||||||
std::thread(handle_client, ssl, client_socket).detach();
|
std::thread(handle_client, ssl, client_socket).detach();
|
||||||
std::cout << "Client connected and secured with TLS 1.3" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up resources
|
// Cleanup
|
||||||
close(server_fd);
|
close(server_fd);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user