I have received a task/project from my professor to build a solution for Web URL filtering. Now this being a very open-ended problem statement to work with, I had multiple ways to approach it. One way is to do the blocking on the client side itself. So, to do that, I first chose an approach of performing a reset attack on my own computer's TCP connection. This way I shall be able to terminate the TCP connection between the blocked IP/URL server and the client's computer. Another approach I could think of was to deploy a proxy server in the middle and sniff all the requests before the data packets manage to reach the blocked host server. This again is a valid approach, however, I am not very sure for how to approach it. I am a novice in the networks domain. Could someone guide me how to proceed from here? I need to implement it for HTTPS as well, however, things complicate with encryption and stuff.
Following is my current implementation of proxy-server approach but just for HTTP:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PROXY_PORT 8080
#define BLACKLISTED_URL "example.net"
void handle_client(int client_socket) {
char request[4096];
ssize_t bytes_received;
// Receive the client's request
bytes_received = recv(client_socket, request, sizeof(request), 0);
// printf("Received request: %s\n", request);
if (bytes_received < 0) {
perror("Error receiving request");
return;
}
// Check if the request contains a blacklisted URL
if (strstr(request, BLACKLISTED_URL) != NULL) {
const char* response = "HTTP/1.1 403 Forbidden\r\nContent-Length: 19\r\n\r\nAccess Denied: URL blocked\r\n";
send(client_socket, response, strlen(response), 0);
close(client_socket);
return;
}
// Create a connection to the target server
int target_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in target_addr;
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(80);
target_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(target_socket, (struct sockaddr*)&target_addr, sizeof(target_addr)) < 0) {
perror("Error connecting to the target server");
close(client_socket);
return;
}
// Forward the request to the target server
send(target_socket, request, bytes_received, 0);
// Forward the response from the target server to the client
char response_buffer[4096];
ssize_t bytes_sent;
while ((bytes_received = recv(target_socket, response_buffer, sizeof(response_buffer), 0)) > 0) {
bytes_sent = send(client_socket, response_buffer, bytes_received, 0);
if (bytes_sent < 0) {
perror("Error sending response to the client");
break;
}
}
// Close the sockets
close(client_socket);
close(target_socket);
}
int main() {
int proxy_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in proxy_addr;
proxy_addr.sin_family = AF_INET;
proxy_addr.sin_port = htons(PROXY_PORT);
proxy_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(proxy_socket, (struct sockaddr*)&proxy_addr, sizeof(proxy_addr)) < 0) {
perror("Error binding to the proxy port");
return 1;
}
if (listen(proxy_socket, 10) < 0) {
perror("Error listening on the proxy socket");
return 1;
}
printf("Proxy server listening on port %d...\n", PROXY_PORT);
while (1) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_socket = accept(proxy_socket, (struct sockaddr*)&client_addr, &client_addr_len);
if (client_socket < 0) {
perror("Error accepting client connection");
} else {
handle_client(client_socket);
}
}
close(proxy_socket);
return 0;
}