feat: Initial code

This commit is contained in:
2025-04-23 17:22:51 +10:00
commit aa3da9d5c3
9 changed files with 640 additions and 0 deletions

197
src/proxy.c Normal file
View File

@@ -0,0 +1,197 @@
#include "proxy.h"
#include "doh.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <netdb.h>
#include <ctype.h>
#define MAX_REQUEST_SIZE 8192
#define MAX_URL_LENGTH 2048
#define THREAD_POOL_SIZE 20
typedef struct {
int client_sock;
} thread_arg_t;
// Extract hostname from HTTP request
char* extract_host(const char* request) {
static char host[MAX_URL_LENGTH];
const char* host_header = strstr(request, "Host: ");
if (host_header) {
host_header += 6; // Skip "Host: "
int i = 0;
while (host_header[i] && host_header[i] != '\r' && host_header[i] != '\n' && i < MAX_URL_LENGTH - 1) {
host[i] = host_header[i];
i++;
}
host[i] = '\0';
return host;
}
return NULL;
}
// Handle client connection in a separate thread
void* handle_client(void* arg) {
thread_arg_t* thread_arg = (thread_arg_t*)arg;
int client_sock = thread_arg->client_sock;
free(thread_arg);
char request[MAX_REQUEST_SIZE];
char buffer[MAX_REQUEST_SIZE];
ssize_t bytes_received = recv(client_sock, request, sizeof(request) - 1, 0);
if (bytes_received <= 0) {
close(client_sock);
return NULL;
}
request[bytes_received] = '\0';
// Extract host from request
char* host = extract_host(request);
if (!host) {
printf("Failed to extract host from request\n");
close(client_sock);
return NULL;
}
printf("Proxying request to: %s\n", host);
// Resolve hostname using DoH
char ip_addr[INET6_ADDRSTRLEN];
if (resolve_doh(host, ip_addr, sizeof(ip_addr)) != 0) {
printf("Failed to resolve hostname using DoH: %s\n", host);
close(client_sock);
return NULL;
}
printf("Resolved %s to %s\n", host, ip_addr);
// Connect to the target server
struct sockaddr_in server_addr;
int server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) {
perror("Cannot create socket to server");
close(client_sock);
return NULL;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip_addr);
server_addr.sin_port = htons(80); // Default to HTTP port
if (connect(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Cannot connect to server");
close(server_sock);
close(client_sock);
return NULL;
}
// Forward the request to the server
if (send(server_sock, request, bytes_received, 0) < 0) {
perror("Failed to send request to server");
close(server_sock);
close(client_sock);
return NULL;
}
// Receive response from server and forward to client
while ((bytes_received = recv(server_sock, buffer, sizeof(buffer), 0)) > 0) {
if (send(client_sock, buffer, bytes_received, 0) < 0) {
perror("Failed to send response to client");
break;
}
}
close(server_sock);
close(client_sock);
return NULL;
}
int start_proxy_server(int port) {
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
// Create socket
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) {
perror("Cannot create socket");
return 1;
}
// Allow reuse of address
int opt = 1;
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
perror("setsockopt failed");
close(server_sock);
return 1;
}
// Initialize server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
// Bind socket
if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(server_sock);
return 1;
}
// Listen for connections
if (listen(server_sock, 10) < 0) {
perror("Listen failed");
close(server_sock);
return 1;
}
printf("Proxy server listening on port %d\n", port);
// Accept and handle client connections
while (1) {
client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_len);
if (client_sock < 0) {
perror("Accept failed");
continue;
}
printf("New connection from %s:%d\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
// Create thread argument
thread_arg_t* thread_arg = malloc(sizeof(thread_arg_t));
if (!thread_arg) {
perror("Failed to allocate memory for thread argument");
close(client_sock);
continue;
}
thread_arg->client_sock = client_sock;
// Create thread to handle client
pthread_t thread_id;
if (pthread_create(&thread_id, NULL, handle_client, thread_arg) != 0) {
perror("Failed to create thread");
free(thread_arg);
close(client_sock);
continue;
}
// Detach thread to allow it to clean up automatically
pthread_detach(thread_id);
}
close(server_sock);
return 0;
}