1 #include <linux/types.h>
2 #include <netinet/in.h>
3 #include <netinet/ip.h>
4 #include <netinet/tcp.h>
9 #include <linux/netfilter.h> /* for NF_ACCEPT */
11 #include <libnetfilter_queue/libnetfilter_queue.h>
13 // Caching of verdicts
14 unsigned int lookup_cache(unsigned char *domain);
15 void add_cache(unsigned char *domain,unsigned int ix);
16 int hash_code(unsigned char *domain);
18 // BAD domains database
19 unsigned int check_domain(unsigned char *domain);
20 void load_domains(char *file);
21 void start_domain_database_loading(void);
22 void end_domain_database_loading(void);
25 * Return packet id, or 0 on error.
27 static u_int32_t get_packet_id(struct nfq_data *tb) {
28 struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr( tb );
29 return ( ph )? ntohl( ph->packet_id ) : 0;
36 //unsigned char pad[12]; // ??
41 static unsigned char *tell_ip(u_int32_t ip) {
42 static unsigned char THEIP[20];
43 unsigned char *b = (unsigned char *)&ip;
44 sprintf( (char*) THEIP, "%d.%d.%d.%d%c", b[0], b[1], b[2], b[3], 0 );
48 static u_int32_t get_dest_ip4(unsigned char *data) {
49 struct headers *p = (struct headers *) data;
50 return p->first.ip_dst.s_addr;
54 * Review payload packet payload
56 static void view_payload(unsigned char *data,int length) {
57 u_int32_t ip4 = get_dest_ip4( data );
58 u_int16_t port = ntohs( ((struct headers *) data )->second.th_dport );
59 u_int8_t syn = sizeof( struct headers );
60 unsigned char *body = data ;//+ sizeof( struct headers );
62 unsigned char * end = body + ( ( length > END )? END : length );
63 fprintf( stderr, "%s %d %d %d ", tell_ip( ip4 ), syn, port, length );
64 while ( body < end ) {
65 unsigned char c = *body++;
66 if ( c < ' ' || c >= 127 || 1 ) {
67 fprintf( stderr, "%02x ", c );
69 fprintf( stderr, "%c", c );
72 fprintf( stderr, "\n" );
76 static unsigned char buffer[1000];
79 * SSL traffic includes a data packet with a clear text host name.
80 * This is knwon as the SNI extension.
82 static unsigned char *ssl_host(unsigned char *data,int length) {
83 // Check that it's a "Client Hello" message
84 unsigned char *p = data + sizeof( struct headers ) + 12;
85 if ( p[0] != 0x16 || p[1] != 0x03 || p[5] != 0x01 || p[6] != 0x00 ) {
88 //fprintf( stderr, "Client Hello\n" );
89 // Note minor version p[2] is not checked
90 // record_length = 256 * p[3] + p[4]
91 // handshake_message_length = 256 * p[7] + p[8]
92 if ( p[9] != 0x03 || p[10] != 0x03 ) { // TLS 1.2 (?ralph?)
95 //fprintf( stderr, "TLS 1.2\n" );
96 unsigned int i = 46 + ( 256 * p[44] ) + p[45];
98 unsigned int extensions_length = ( 256 * p[i] ) + p[i+1];
101 //fprintf( stderr, "TLS 1.2 %d %d\n", i, extensions_length );
102 while ( k < extensions_length ) {
103 unsigned int type = ( 256 * p[i+k] ) + p[i+k+1];
105 unsigned int length = ( 256 * p[i+k] ) + p[i+k+1];
107 //fprintf( stderr, "Extension %d %d\n", k-4, type );
108 if ( type == 0 ) { // Server Name
110 break; // Name badness
112 unsigned int name_length = ( 256 * p[i+k+3] ) + p[i+k+4];
113 unsigned char *path = &p[i+k+5];
114 memcpy( buffer, path, name_length );
115 buffer[ name_length ] = '\0';
120 // This point is only reached on "missing or bad SNI".
121 view_payload( data, length );
126 * HTTP traffic includes a data packet with the host name as a
129 static unsigned char *http_host(unsigned char *data,int length) {
130 unsigned char *body = data + sizeof( struct headers );
131 if ( ( strncmp( (char*) body, "GET ", 4 ) != 0 ) &&
132 ( strncmp( (char*) body, "POST ", 5 ) != 0 ) ) {
135 unsigned char *end = data + length - 6;
137 for ( ; body < end; body++ ) {
139 if ( strncmp( (char*) body, "Host:", 5 ) == 0 ) {
141 for( ; body < end; body++ ) if ( *body != ' ' ) break;
142 unsigned char *start = body;
144 for( ; body < end; n++, body++ ) if ( *body <= ' ' ) break;
148 memcpy( buffer, start, n );
152 if ( strncmp( (char*) body, "\r\n", 2 ) == 0 ) {
155 for( ; body < end; body++ ) if ( *body == '\n' ) break;
160 check = ( *body == '\n' );
166 * Callback function to handle a packet.
169 struct nfq_q_handle *qh,
170 struct nfgenmsg *nfmsg,
171 struct nfq_data *nfa, void *code )
173 u_int32_t id = get_packet_id( nfa );
175 int length = nfq_get_payload( nfa, &data);
176 int verdict = NF_ACCEPT;
177 u_int32_t ip4 = get_dest_ip4( data );
179 fprintf( stderr, "PKT %s %d\n", tell_ip( ip4 ), length );
181 if ( length >= 100 ) {
182 unsigned char *host = http_host( data, length );
184 fprintf( stderr, "HTTP HOST %s %s\n", tell_ip( ip4 ), host );
187 host = ssl_host( data, length );
189 fprintf( stderr, "SSL HOST %s %s\n", tell_ip( ip4 ), host );
193 int i = lookup_cache( host );
195 unsigned int ix = check_domain( host );
196 add_cache( host, ix );
198 fprintf( stderr, "%s %d %s ** %d\n",
199 tell_ip( ip4 ), hash_code( host ), host, ix );
204 } else if ( i > 0 ) {
209 return nfq_set_verdict(qh, id, verdict, 0, NULL);
213 * Program main function.
215 int main(int argc, char **argv) {
217 start_domain_database_loading();
219 for ( ; n < argc; n++ ) {
220 fprintf( stderr, "Loading blacklist %s\n", argv[ n ] );
221 load_domains( argv[ n ] );
223 end_domain_database_loading();
225 struct nfq_handle *h;
226 struct nfq_q_handle *qh;
227 //struct nfnl_handle *nh;
230 char buf[4096] __attribute__ ((aligned));
232 fprintf( stderr, "opening library handle\n");
235 fprintf(stderr, "error during nfq_open()\n");
239 fprintf( stderr, "unbinding any existing nf_queue handler\n" );
240 if ( nfq_unbind_pf(h, AF_INET) < 0 ) {
241 fprintf(stderr, "error during nfq_unbind_pf()\n");
245 fprintf( stderr, "binding nfnetlink_queue as nf_queue handler\n" );
246 if ( nfq_bind_pf(h, AF_INET) < 0 ) {
247 fprintf(stderr, "error during nfq_bind_pf()\n");
252 fprintf( stderr, "binding this socket to queue '%d'\n", THEQUEUE );
253 qh = nfq_create_queue( h, THEQUEUE, &cb, NULL );
255 fprintf(stderr, "error during nfq_create_queue()\n");
259 fprintf( stderr, "setting copy_packet mode\n" );
260 if ( nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff ) < 0) {
261 fprintf(stderr, "can't set packet_copy mode\n");
267 while ( ( rv = recv(fd, buf, sizeof(buf), 0) ) && rv >= 0 ) {
268 //printf( "pkt received\n" );
269 nfq_handle_packet(h, buf, rv);
272 fprintf( stderr, "unbinding from queue %d\n", THEQUEUE);
273 nfq_destroy_queue(qh);
276 /* normally, applications SHOULD NOT issue this command, since it
277 detaches other programs/sockets from AF_INET, too ! */
278 fprintf( stderr, "unbinding from AF_INET\n");
279 nfq_unbind_pf(h, AF_INET);
282 fprintf( stderr, "closing library handle\n");