mirror of
https://github.com/bol-van/zapret.git
synced 2025-04-20 05:52:57 +03:00
tpws,nfqws : remove cap library dependency
This commit is contained in:
parent
2595d0ebd0
commit
c69a31cc1d
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS += -std=c99 -s -O3
|
CFLAGS += -std=c99 -s -O3
|
||||||
LIBS = -lnetfilter_queue -lnfnetlink -lcap -lz
|
LIBS = -lnetfilter_queue -lnfnetlink -lz
|
||||||
SRC_FILES = *.c
|
SRC_FILES = *.c
|
||||||
|
|
||||||
all: nfqws
|
all: nfqws
|
||||||
|
148
nfq/darkmagic.c
148
nfq/darkmagic.c
@ -10,65 +10,138 @@ uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
|||||||
return htonl(ntohl(netorder_value)+cpuorder_increment);
|
return htonl(ntohl(netorder_value)+cpuorder_increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
|
||||||
|
{
|
||||||
|
char *t = (char*)(tcp+1);
|
||||||
|
char *end = (char*)tcp + (tcp->doff<<2);
|
||||||
|
while(t<end)
|
||||||
|
{
|
||||||
|
switch(*t)
|
||||||
|
{
|
||||||
|
case 0: // end
|
||||||
|
break;
|
||||||
|
case 1: // noop
|
||||||
|
t++;
|
||||||
|
break;
|
||||||
|
default: // kind,len,data
|
||||||
|
if ((t+1)>=end || (t+t[1])>end)
|
||||||
|
break;
|
||||||
|
if (*t==kind)
|
||||||
|
return t;
|
||||||
|
t+=t[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint32_t *tcp_find_timestamps(struct tcphdr *tcp)
|
||||||
|
{
|
||||||
|
uint8_t *t = tcp_find_option(tcp,8);
|
||||||
|
return (t && t[1]==10) ? (uint32_t*)(t+2) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, enum tcp_fooling_mode fooling, uint16_t nsport, uint16_t ndport, uint16_t nwsize)
|
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, uint8_t fooling, uint16_t nsport, uint16_t ndport, uint16_t nwsize, uint32_t *timestamps)
|
||||||
{
|
{
|
||||||
char *tcpopt = (char*)(tcp+1);
|
char *tcpopt = (char*)(tcp+1);
|
||||||
|
uint8_t t=0;
|
||||||
|
|
||||||
memset(tcp,0,sizeof(*tcp));
|
memset(tcp,0,sizeof(*tcp));
|
||||||
tcp->source = nsport;
|
tcp->source = nsport;
|
||||||
tcp->dest = ndport;
|
tcp->dest = ndport;
|
||||||
tcp->seq = seq;
|
if (fooling & TCP_FOOL_BADSEQ)
|
||||||
tcp->ack_seq = ack_seq;
|
{
|
||||||
|
tcp->seq = net32_add(seq,0x80000000);
|
||||||
|
tcp->ack_seq = net32_add(ack_seq,0x80000000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcp->seq = seq;
|
||||||
|
tcp->ack_seq = ack_seq;
|
||||||
|
}
|
||||||
tcp->doff = 5;
|
tcp->doff = 5;
|
||||||
*((uint8_t*)tcp+13)= tcp_flags;
|
*((uint8_t*)tcp+13)= tcp_flags;
|
||||||
tcp->window = nwsize;
|
tcp->window = nwsize;
|
||||||
if (fooling==TCP_FOOL_MD5SIG)
|
if (fooling & TCP_FOOL_MD5SIG)
|
||||||
{
|
{
|
||||||
tcp->doff += 5; // +20 bytes
|
|
||||||
tcpopt[0] = 19; // kind
|
tcpopt[0] = 19; // kind
|
||||||
tcpopt[1] = 18; // len
|
tcpopt[1] = 18; // len
|
||||||
*(uint32_t*)(tcpopt+2)=random();
|
*(uint32_t*)(tcpopt+2)=random();
|
||||||
*(uint32_t*)(tcpopt+6)=random();
|
*(uint32_t*)(tcpopt+6)=random();
|
||||||
*(uint32_t*)(tcpopt+10)=random();
|
*(uint32_t*)(tcpopt+10)=random();
|
||||||
*(uint32_t*)(tcpopt+14)=random();
|
*(uint32_t*)(tcpopt+14)=random();
|
||||||
tcpopt[18] = 0; // end
|
t=18;
|
||||||
tcpopt[19] = 0;
|
|
||||||
}
|
}
|
||||||
|
if (timestamps || (fooling & TCP_FOOL_TS))
|
||||||
|
{
|
||||||
|
tcpopt[t] = 8; // kind
|
||||||
|
tcpopt[t+1] = 10; // len
|
||||||
|
// forge only TSecr if orig timestamp is present
|
||||||
|
*(uint32_t*)(tcpopt+t+2) = timestamps ? timestamps[0] : -1;
|
||||||
|
*(uint32_t*)(tcpopt+t+6) = (timestamps && !(fooling & TCP_FOOL_TS)) ? timestamps[1] : -1;
|
||||||
|
t+=10;
|
||||||
|
}
|
||||||
|
while (t&3) tcpopt[t++]=1; // noop
|
||||||
|
tcp->doff += t>>2;
|
||||||
|
}
|
||||||
|
static uint16_t tcpopt_len(uint8_t fooling, uint32_t *timestamps)
|
||||||
|
{
|
||||||
|
uint16_t t=0;
|
||||||
|
if (fooling & TCP_FOOL_MD5SIG) t=18;
|
||||||
|
if ((fooling & TCP_FOOL_TS) || timestamps) t+=10;
|
||||||
|
return (t+3)&~3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rawsend_sock=-1;
|
static int rawsend_sock4=-1, rawsend_sock6=-1;
|
||||||
void rawsend_cleanup()
|
static void rawsend_clean_sock(int *sock)
|
||||||
{
|
{
|
||||||
if (rawsend_sock!=-1)
|
if (sock && *sock!=-1)
|
||||||
{
|
{
|
||||||
close(rawsend_sock);
|
close(*sock);
|
||||||
rawsend_sock=-1;
|
*sock=-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void rawsend_socket(int family,uint32_t fwmark)
|
void rawsend_cleanup()
|
||||||
{
|
{
|
||||||
if (rawsend_sock==-1)
|
rawsend_clean_sock(&rawsend_sock4);
|
||||||
|
rawsend_clean_sock(&rawsend_sock6);
|
||||||
|
}
|
||||||
|
static int *rawsend_family_sock(int family)
|
||||||
|
{
|
||||||
|
switch(family)
|
||||||
|
{
|
||||||
|
case AF_INET: return &rawsend_sock4;
|
||||||
|
case AF_INET6: return &rawsend_sock6;
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int rawsend_socket(int family,uint32_t fwmark)
|
||||||
|
{
|
||||||
|
int *sock = rawsend_family_sock(family);
|
||||||
|
if (!sock) return -1;
|
||||||
|
|
||||||
|
if (*sock==-1)
|
||||||
{
|
{
|
||||||
int yes=1,pri=6;
|
int yes=1,pri=6;
|
||||||
rawsend_sock = socket(family, SOCK_RAW, IPPROTO_RAW);
|
*sock = socket(family, SOCK_RAW, IPPROTO_RAW);
|
||||||
if (rawsend_sock==-1)
|
if (*sock==-1)
|
||||||
perror("rawsend: socket()");
|
perror("rawsend: socket()");
|
||||||
else if (setsockopt(rawsend_sock, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)) == -1)
|
else if (setsockopt(*sock, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)) == -1)
|
||||||
{
|
{
|
||||||
perror("rawsend: setsockopt(SO_MARK)");
|
perror("rawsend: setsockopt(SO_MARK)");
|
||||||
rawsend_cleanup();
|
rawsend_clean_sock(sock);
|
||||||
}
|
}
|
||||||
else if (setsockopt(rawsend_sock, SOL_SOCKET, SO_PRIORITY, &pri, sizeof(pri)) == -1)
|
else if (setsockopt(*sock, SOL_SOCKET, SO_PRIORITY, &pri, sizeof(pri)) == -1)
|
||||||
{
|
{
|
||||||
perror("rawsend: setsockopt(SO_PRIORITY)");
|
perror("rawsend: setsockopt(SO_PRIORITY)");
|
||||||
rawsend_cleanup();
|
rawsend_clean_sock(sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return *sock;
|
||||||
}
|
}
|
||||||
bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len)
|
bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len)
|
||||||
{
|
{
|
||||||
rawsend_socket(dst->sa_family,fwmark);
|
int sock=rawsend_socket(dst->sa_family,fwmark);
|
||||||
if (rawsend_sock==-1) return false;
|
if (sock==-1) return false;
|
||||||
|
|
||||||
int salen = dst->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
|
int salen = dst->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
|
||||||
struct sockaddr_storage dst2;
|
struct sockaddr_storage dst2;
|
||||||
@ -76,7 +149,7 @@ bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len)
|
|||||||
if (dst->sa_family==AF_INET6)
|
if (dst->sa_family==AF_INET6)
|
||||||
((struct sockaddr_in6 *)&dst2)->sin6_port = 0; // or will be EINVAL
|
((struct sockaddr_in6 *)&dst2)->sin6_port = 0; // or will be EINVAL
|
||||||
|
|
||||||
int bytes = sendto(rawsend_sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
int bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
||||||
if (bytes==-1)
|
if (bytes==-1)
|
||||||
{
|
{
|
||||||
perror("rawsend: sendto");
|
perror("rawsend: sendto");
|
||||||
@ -89,14 +162,14 @@ bool prepare_tcp_segment4(
|
|||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
uint32_t seq, uint32_t ack_seq,
|
uint32_t seq, uint32_t ack_seq,
|
||||||
uint16_t wsize,
|
uint16_t wsize,
|
||||||
|
uint32_t *timestamps,
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
enum tcp_fooling_mode fooling,
|
uint8_t fooling,
|
||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
char *buf, size_t *buflen)
|
char *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
uint16_t tcpoptlen = 0;
|
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps);
|
||||||
if (fooling==TCP_FOOL_MD5SIG) tcpoptlen=20;
|
uint16_t pktlen = sizeof(struct iphdr) + sizeof(struct tcphdr) + tcpoptlen + len;
|
||||||
uint16_t pktlen = sizeof(struct iphdr) + sizeof(struct tcphdr) + tcpoptlen + len;
|
|
||||||
if (pktlen>*buflen)
|
if (pktlen>*buflen)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"prepare_tcp_segment : packet len cannot exceed %zu\n",*buflen);
|
fprintf(stderr,"prepare_tcp_segment : packet len cannot exceed %zu\n",*buflen);
|
||||||
@ -116,11 +189,11 @@ bool prepare_tcp_segment4(
|
|||||||
ip->saddr = src->sin_addr.s_addr;
|
ip->saddr = src->sin_addr.s_addr;
|
||||||
ip->daddr = dst->sin_addr.s_addr;
|
ip->daddr = dst->sin_addr.s_addr;
|
||||||
|
|
||||||
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port,wsize);
|
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port,wsize,timestamps);
|
||||||
|
|
||||||
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
|
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
|
||||||
tcp_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,ip->saddr,ip->daddr);
|
tcp_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,ip->saddr,ip->daddr);
|
||||||
if (fooling==TCP_FOOL_BADSUM) tcp->check^=0xBEAF;
|
if (fooling & TCP_FOOL_BADSUM) tcp->check^=0xBEAF;
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -132,13 +205,13 @@ bool prepare_tcp_segment6(
|
|||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
uint32_t seq, uint32_t ack_seq,
|
uint32_t seq, uint32_t ack_seq,
|
||||||
uint16_t wsize,
|
uint16_t wsize,
|
||||||
|
uint32_t *timestamps,
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
enum tcp_fooling_mode fooling,
|
uint8_t fooling,
|
||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
char *buf, size_t *buflen)
|
char *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
uint16_t tcpoptlen = 0;
|
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps);
|
||||||
if (fooling==TCP_FOOL_MD5SIG) tcpoptlen=20;
|
|
||||||
uint16_t payloadlen = sizeof(struct tcphdr) + tcpoptlen + len;
|
uint16_t payloadlen = sizeof(struct tcphdr) + tcpoptlen + len;
|
||||||
uint16_t pktlen = sizeof(struct ip6_hdr) + payloadlen;
|
uint16_t pktlen = sizeof(struct ip6_hdr) + payloadlen;
|
||||||
if (pktlen>*buflen)
|
if (pktlen>*buflen)
|
||||||
@ -157,11 +230,11 @@ bool prepare_tcp_segment6(
|
|||||||
ip6->ip6_src = src->sin6_addr;
|
ip6->ip6_src = src->sin6_addr;
|
||||||
ip6->ip6_dst = dst->sin6_addr;
|
ip6->ip6_dst = dst->sin6_addr;
|
||||||
|
|
||||||
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin6_port,dst->sin6_port,wsize);
|
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin6_port,dst->sin6_port,wsize,timestamps);
|
||||||
|
|
||||||
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
|
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
|
||||||
tcp6_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip6->ip6_src,&ip6->ip6_dst);
|
tcp6_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip6->ip6_src,&ip6->ip6_dst);
|
||||||
if (fooling==TCP_FOOL_BADSUM) tcp->check^=0xBEAF;
|
if (fooling & TCP_FOOL_BADSUM) tcp->check^=0xBEAF;
|
||||||
|
|
||||||
*buflen = pktlen;
|
*buflen = pktlen;
|
||||||
return true;
|
return true;
|
||||||
@ -172,15 +245,16 @@ bool prepare_tcp_segment(
|
|||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
uint32_t seq, uint32_t ack_seq,
|
uint32_t seq, uint32_t ack_seq,
|
||||||
uint16_t wsize,
|
uint16_t wsize,
|
||||||
|
uint32_t *timestamps,
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
enum tcp_fooling_mode fooling,
|
uint8_t fooling,
|
||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
char *buf, size_t *buflen)
|
char *buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
||||||
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,seq,ack_seq,wsize,ttl,fooling,data,len,buf,buflen) :
|
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,seq,ack_seq,wsize,timestamps,ttl,fooling,data,len,buf,buflen) :
|
||||||
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
||||||
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,seq,ack_seq,wsize,ttl,fooling,data,len,buf,buflen) :
|
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,seq,ack_seq,wsize,timestamps,ttl,fooling,data,len,buf,buflen) :
|
||||||
false;
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,19 +12,21 @@
|
|||||||
// returns netorder value
|
// returns netorder value
|
||||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
|
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
|
||||||
|
|
||||||
enum tcp_fooling_mode {
|
#define TCP_FOOL_NONE 0
|
||||||
TCP_FOOL_NONE=0,
|
#define TCP_FOOL_MD5SIG 1
|
||||||
TCP_FOOL_MD5SIG=1,
|
#define TCP_FOOL_BADSUM 2
|
||||||
TCP_FOOL_BADSUM=2
|
#define TCP_FOOL_TS 4
|
||||||
};
|
#define TCP_FOOL_BADSEQ 8
|
||||||
|
|
||||||
// seq and wsize have network byte order
|
// seq and wsize have network byte order
|
||||||
bool prepare_tcp_segment4(
|
bool prepare_tcp_segment4(
|
||||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
uint32_t seq, uint32_t ack_seq,
|
uint32_t seq, uint32_t ack_seq,
|
||||||
uint16_t wsize,
|
uint16_t wsize,
|
||||||
|
uint32_t *timestamps,
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
enum tcp_fooling_mode fooling,
|
uint8_t fooling,
|
||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
char *buf, size_t *buflen);
|
char *buf, size_t *buflen);
|
||||||
bool prepare_tcp_segment6(
|
bool prepare_tcp_segment6(
|
||||||
@ -32,8 +34,9 @@ bool prepare_tcp_segment6(
|
|||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
uint32_t seq, uint32_t ack_seq,
|
uint32_t seq, uint32_t ack_seq,
|
||||||
uint16_t wsize,
|
uint16_t wsize,
|
||||||
|
uint32_t *timestamps,
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
enum tcp_fooling_mode fooling,
|
uint8_t fooling,
|
||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
char *buf, size_t *buflen);
|
char *buf, size_t *buflen);
|
||||||
bool prepare_tcp_segment(
|
bool prepare_tcp_segment(
|
||||||
@ -41,12 +44,15 @@ bool prepare_tcp_segment(
|
|||||||
uint8_t tcp_flags,
|
uint8_t tcp_flags,
|
||||||
uint32_t seq, uint32_t ack_seq,
|
uint32_t seq, uint32_t ack_seq,
|
||||||
uint16_t wsize,
|
uint16_t wsize,
|
||||||
|
uint32_t *timestamps,
|
||||||
uint8_t ttl,
|
uint8_t ttl,
|
||||||
enum tcp_fooling_mode fooling,
|
uint8_t fooling,
|
||||||
const void *data, uint16_t len,
|
const void *data, uint16_t len,
|
||||||
char *buf, size_t *buflen);
|
char *buf, size_t *buflen);
|
||||||
|
|
||||||
void extract_endpoints(const struct iphdr *iphdr,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
|
void extract_endpoints(const struct iphdr *iphdr,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
|
||||||
|
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
|
||||||
|
uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
|
||||||
|
|
||||||
// auto creates internal socket and uses it for subsequent calls
|
// auto creates internal socket and uses it for subsequent calls
|
||||||
bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len);
|
bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len);
|
||||||
|
46
nfq/nfqws.c
46
nfq/nfqws.c
@ -91,7 +91,7 @@ struct params_s
|
|||||||
bool desync_retrans,desync_skip_nosni,desync_any_proto;
|
bool desync_retrans,desync_skip_nosni,desync_any_proto;
|
||||||
int desync_split_pos;
|
int desync_split_pos;
|
||||||
uint8_t desync_ttl;
|
uint8_t desync_ttl;
|
||||||
enum tcp_fooling_mode desync_tcp_fooling_mode;
|
uint8_t desync_tcp_fooling_mode;
|
||||||
uint32_t desync_fwmark;
|
uint32_t desync_fwmark;
|
||||||
char hostfile[256];
|
char hostfile[256];
|
||||||
strpool *hostlist;
|
strpool *hostlist;
|
||||||
@ -467,7 +467,7 @@ static bool modify_tcp_packet(uint8_t *data, size_t len, struct tcphdr *tcphdr)
|
|||||||
|
|
||||||
|
|
||||||
// result : true - drop original packet, false = dont drop
|
// result : true - drop original packet, false = dont drop
|
||||||
static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const struct iphdr *iphdr, const struct ip6_hdr *ip6hdr, const struct tcphdr *tcphdr, const uint8_t *data_payload, size_t len_payload)
|
static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, struct iphdr *iphdr, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, uint8_t *data_payload, size_t len_payload)
|
||||||
{
|
{
|
||||||
if (!!iphdr == !!ip6hdr) return false; // one and only one must be present
|
if (!!iphdr == !!ip6hdr) return false; // one and only one must be present
|
||||||
|
|
||||||
@ -535,11 +535,12 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
|
|||||||
uint8_t ttl_orig = iphdr ? iphdr->ttl : ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim;
|
uint8_t ttl_orig = iphdr ? iphdr->ttl : ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim;
|
||||||
uint8_t ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
|
uint8_t ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
|
||||||
uint8_t flags_orig = *((uint8_t*)tcphdr+13);
|
uint8_t flags_orig = *((uint8_t*)tcphdr+13);
|
||||||
|
uint32_t *timestamps = tcp_find_timestamps(tcphdr);
|
||||||
|
|
||||||
switch(params.desync_mode)
|
switch(params.desync_mode)
|
||||||
{
|
{
|
||||||
case DESYNC_FAKE:
|
case DESYNC_FAKE:
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps,
|
||||||
ttl_fake,params.desync_tcp_fooling_mode,
|
ttl_fake,params.desync_tcp_fooling_mode,
|
||||||
fake, fake_size, newdata, &newlen))
|
fake, fake_size, newdata, &newlen))
|
||||||
{
|
{
|
||||||
@ -548,7 +549,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
|
|||||||
break;
|
break;
|
||||||
case DESYNC_RST:
|
case DESYNC_RST:
|
||||||
case DESYNC_RSTACK:
|
case DESYNC_RSTACK:
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (params.desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (params.desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps,
|
||||||
ttl_fake,params.desync_tcp_fooling_mode,
|
ttl_fake,params.desync_tcp_fooling_mode,
|
||||||
NULL, 0, newdata, &newlen))
|
NULL, 0, newdata, &newlen))
|
||||||
{
|
{
|
||||||
@ -565,7 +566,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
|
|||||||
if (split_pos<len_payload)
|
if (split_pos<len_payload)
|
||||||
{
|
{
|
||||||
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu\n",split_pos,len_payload-1, len_payload-split_pos)
|
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu\n",split_pos,len_payload-1, len_payload-split_pos)
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->seq,split_pos), tcphdr->ack_seq, tcphdr->window,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->seq,split_pos), tcphdr->ack_seq, tcphdr->window, timestamps,
|
||||||
ttl_orig,TCP_FOOL_NONE,
|
ttl_orig,TCP_FOOL_NONE,
|
||||||
data_payload+split_pos, len_payload-split_pos, newdata, &newlen) ||
|
data_payload+split_pos, len_payload-split_pos, newdata, &newlen) ||
|
||||||
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||||
@ -579,7 +580,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
|
|||||||
{
|
{
|
||||||
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos)
|
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos)
|
||||||
fakeseg_len = sizeof(fakeseg);
|
fakeseg_len = sizeof(fakeseg);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps,
|
||||||
ttl_fake,params.desync_tcp_fooling_mode,
|
ttl_fake,params.desync_tcp_fooling_mode,
|
||||||
zeropkt, split_pos, fakeseg, &fakeseg_len) ||
|
zeropkt, split_pos, fakeseg, &fakeseg_len) ||
|
||||||
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||||
@ -591,7 +592,7 @@ static bool dpi_desync_packet(const uint8_t *data_pkt, size_t len_pkt, const str
|
|||||||
|
|
||||||
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos)
|
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu\n",split_pos-1, split_pos)
|
||||||
newlen = sizeof(newdata);
|
newlen = sizeof(newdata);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->seq, tcphdr->ack_seq, tcphdr->window, timestamps,
|
||||||
ttl_orig,TCP_FOOL_NONE,
|
ttl_orig,TCP_FOOL_NONE,
|
||||||
data_payload, split_pos, newdata, &newlen) ||
|
data_payload, split_pos, newdata, &newlen) ||
|
||||||
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||||
@ -734,7 +735,7 @@ static void exithelp()
|
|||||||
" --dpi-desync[=<mode>]\t\t\t; try to desync dpi state. modes : fake rst rstack disorder disorder2\n"
|
" --dpi-desync[=<mode>]\t\t\t; try to desync dpi state. modes : fake rst rstack disorder disorder2\n"
|
||||||
" --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X\n"
|
" --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X\n"
|
||||||
" --dpi-desync-ttl=<int>\t\t\t; set ttl for desync packet\n"
|
" --dpi-desync-ttl=<int>\t\t\t; set ttl for desync packet\n"
|
||||||
" --dpi-desync-fooling=none|md5sig|badsum\n"
|
" --dpi-desync-fooling=none|md5sig|ts|badseq|badsum\t; can use multiple comma separated values\n"
|
||||||
" --dpi-desync-retrans=0|1\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n"
|
" --dpi-desync-retrans=0|1\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n"
|
||||||
" --dpi-desync-skip-nosni=0|1\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n"
|
" --dpi-desync-skip-nosni=0|1\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n"
|
||||||
" --dpi-desync-split-pos=<1..%zu>\t; (for disorder only) split TCP packet at specified position\n"
|
" --dpi-desync-split-pos=<1..%zu>\t; (for disorder only) split TCP packet at specified position\n"
|
||||||
@ -911,16 +912,27 @@ int main(int argc, char **argv)
|
|||||||
params.desync_ttl = (uint8_t)atoi(optarg);
|
params.desync_ttl = (uint8_t)atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 13: /* dpi-desync-fooling */
|
case 13: /* dpi-desync-fooling */
|
||||||
if (!strcmp(optarg,"none"))
|
|
||||||
params.desync_tcp_fooling_mode = TCP_FOOL_NONE;
|
|
||||||
else if (!strcmp(optarg,"md5sig"))
|
|
||||||
params.desync_tcp_fooling_mode = TCP_FOOL_MD5SIG;
|
|
||||||
else if (!strcmp(optarg,"badsum"))
|
|
||||||
params.desync_tcp_fooling_mode = TCP_FOOL_BADSUM;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-fooling allowed values : none,md5sig,badsum\n");
|
char *e,*p = optarg;
|
||||||
exit_clean(1);
|
while (p)
|
||||||
|
{
|
||||||
|
e = strchr(p,',');
|
||||||
|
if (e) *e++=0;
|
||||||
|
if (!strcmp(p,"md5sig"))
|
||||||
|
params.desync_tcp_fooling_mode |= TCP_FOOL_MD5SIG;
|
||||||
|
else if (!strcmp(p,"ts"))
|
||||||
|
params.desync_tcp_fooling_mode |= TCP_FOOL_TS;
|
||||||
|
else if (!strcmp(p,"badsum"))
|
||||||
|
params.desync_tcp_fooling_mode |= TCP_FOOL_BADSUM;
|
||||||
|
else if (!strcmp(p,"badseq"))
|
||||||
|
params.desync_tcp_fooling_mode |= TCP_FOOL_BADSEQ;
|
||||||
|
else if (strcmp(p,"none"))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "dpi-desync-fooling allowed values : none,md5sig,ts,badseq,badsum\n");
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
p = e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14: /* dpi-desync-retrans */
|
case 14: /* dpi-desync-retrans */
|
||||||
|
48
nfq/sec.c
48
nfq/sec.c
@ -5,26 +5,26 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
bool setpcap(cap_value_t *caps, int ncaps)
|
bool checkpcap(uint64_t caps)
|
||||||
{
|
{
|
||||||
cap_t capabilities;
|
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
|
||||||
|
struct __user_cap_data_struct cd[2];
|
||||||
|
uint32_t c0 = (uint32_t)caps;
|
||||||
|
uint32_t c1 = (uint32_t)(caps>>32);
|
||||||
|
|
||||||
if (!(capabilities = cap_init()))
|
return !capget(&ch,cd) && (cd[0].effective & c0)==c0 && (cd[0].effective & c1)==c1;
|
||||||
return false;
|
}
|
||||||
|
bool setpcap(uint64_t caps)
|
||||||
|
{
|
||||||
|
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
|
||||||
|
struct __user_cap_data_struct cd[2];
|
||||||
|
|
||||||
if (ncaps && (cap_set_flag(capabilities, CAP_PERMITTED, ncaps, caps, CAP_SET) ||
|
cd[0].effective = cd[0].permitted = (uint32_t)caps;
|
||||||
cap_set_flag(capabilities, CAP_EFFECTIVE, ncaps, caps, CAP_SET)))
|
cd[0].inheritable = 0;
|
||||||
{
|
cd[1].effective = cd[1].permitted = (uint32_t)(caps>>32);
|
||||||
cap_free(capabilities);
|
cd[1].inheritable = 0;
|
||||||
return false;
|
|
||||||
}
|
return !capset(&ch,cd);
|
||||||
if (cap_set_proc(capabilities))
|
|
||||||
{
|
|
||||||
cap_free(capabilities);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cap_free(capabilities);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
int getmaxcap()
|
int getmaxcap()
|
||||||
{
|
{
|
||||||
@ -40,27 +40,25 @@ int getmaxcap()
|
|||||||
}
|
}
|
||||||
bool dropcaps()
|
bool dropcaps()
|
||||||
{
|
{
|
||||||
// must have CAP_SETPCAP at the end. its required to clear bounding set
|
uint64_t caps = (1<<CAP_NET_ADMIN)|(1<<CAP_NET_RAW);
|
||||||
cap_value_t cap_values[] = { CAP_NET_ADMIN,CAP_NET_RAW,CAP_SETPCAP };
|
|
||||||
int capct = sizeof(cap_values) / sizeof(*cap_values);
|
|
||||||
int maxcap = getmaxcap();
|
int maxcap = getmaxcap();
|
||||||
|
|
||||||
if (setpcap(cap_values, capct))
|
if (setpcap(caps|(1<<CAP_SETPCAP)))
|
||||||
{
|
{
|
||||||
for (int cap = 0; cap <= maxcap; cap++)
|
for (int cap = 0; cap <= maxcap; cap++)
|
||||||
{
|
{
|
||||||
if (cap_drop_bound(cap))
|
if (prctl(PR_CAPBSET_DROP, cap)<0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not drop cap %d\n", cap);
|
fprintf(stderr, "could not drop bound cap %d\n", cap);
|
||||||
perror("cap_drop_bound");
|
perror("cap_drop_bound");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// now without CAP_SETPCAP
|
// now without CAP_SETPCAP
|
||||||
if (!setpcap(cap_values, capct - 1))
|
if (!setpcap(caps))
|
||||||
{
|
{
|
||||||
perror("setpcap");
|
perror("setpcap");
|
||||||
return false;
|
return checkpcap(caps);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
bool setpcap(cap_value_t *caps, int ncaps);
|
bool setpcap(uint64_t caps);
|
||||||
int getmaxcap();
|
int getmaxcap();
|
||||||
bool dropcaps();
|
bool dropcaps();
|
||||||
bool droproot(uid_t uid, gid_t gid);
|
bool droproot(uid_t uid, gid_t gid);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS += -std=c99 -s -O3
|
CFLAGS += -std=c99 -s -O3
|
||||||
LIBS = -lz -lcap
|
LIBS = -lz
|
||||||
SRC_FILES = *.c
|
SRC_FILES = *.c
|
||||||
|
|
||||||
all: tpws
|
all: tpws
|
||||||
|
126
tpws/sec.c
Normal file
126
tpws/sec.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sec.h"
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
bool checkpcap(uint64_t caps)
|
||||||
|
{
|
||||||
|
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
|
||||||
|
struct __user_cap_data_struct cd[2];
|
||||||
|
uint32_t c0 = (uint32_t)caps;
|
||||||
|
uint32_t c1 = (uint32_t)(caps>>32);
|
||||||
|
|
||||||
|
return !capget(&ch,cd) && (cd[0].effective & c0)==c0 && (cd[0].effective & c1)==c1;
|
||||||
|
}
|
||||||
|
bool setpcap(uint64_t caps)
|
||||||
|
{
|
||||||
|
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
|
||||||
|
struct __user_cap_data_struct cd[2];
|
||||||
|
|
||||||
|
cd[0].effective = cd[0].permitted = (uint32_t)caps;
|
||||||
|
cd[0].inheritable = 0;
|
||||||
|
cd[1].effective = cd[1].permitted = (uint32_t)(caps>>32);
|
||||||
|
cd[1].inheritable = 0;
|
||||||
|
|
||||||
|
return !capset(&ch,cd);
|
||||||
|
}
|
||||||
|
int getmaxcap()
|
||||||
|
{
|
||||||
|
int maxcap = CAP_LAST_CAP;
|
||||||
|
FILE *F = fopen("/proc/sys/kernel/cap_last_cap", "r");
|
||||||
|
if (F)
|
||||||
|
{
|
||||||
|
int n = fscanf(F, "%d", &maxcap);
|
||||||
|
fclose(F);
|
||||||
|
}
|
||||||
|
return maxcap;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool dropcaps()
|
||||||
|
{
|
||||||
|
uint64_t caps = 0;
|
||||||
|
int maxcap = getmaxcap();
|
||||||
|
|
||||||
|
if (setpcap(caps|(1<<CAP_SETPCAP)))
|
||||||
|
{
|
||||||
|
for (int cap = 0; cap <= maxcap; cap++)
|
||||||
|
{
|
||||||
|
if (prctl(PR_CAPBSET_DROP, cap)<0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "could not drop bound cap %d\n", cap);
|
||||||
|
perror("cap_drop_bound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now without CAP_SETPCAP
|
||||||
|
if (!setpcap(caps))
|
||||||
|
{
|
||||||
|
perror("setpcap");
|
||||||
|
return checkpcap(caps);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool droproot(uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
if (uid || gid)
|
||||||
|
{
|
||||||
|
if (prctl(PR_SET_KEEPCAPS, 1L))
|
||||||
|
{
|
||||||
|
perror("prctl(PR_SET_KEEPCAPS): ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (setgid(gid))
|
||||||
|
{
|
||||||
|
perror("setgid: ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (setuid(uid))
|
||||||
|
{
|
||||||
|
perror("setuid: ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dropcaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
void daemonize()
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == -1)
|
||||||
|
{
|
||||||
|
perror("fork: ");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
else if (pid != 0)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
if (setsid() == -1)
|
||||||
|
exit(2);
|
||||||
|
if (chdir("/") == -1)
|
||||||
|
exit(2);
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
/* redirect fd's 0,1,2 to /dev/null */
|
||||||
|
open("/dev/null", O_RDWR);
|
||||||
|
int fd;
|
||||||
|
/* stdin */
|
||||||
|
fd = dup(0);
|
||||||
|
/* stdout */
|
||||||
|
fd = dup(0);
|
||||||
|
/* stderror */
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writepid(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *F;
|
||||||
|
if (!(F = fopen(filename, "w")))
|
||||||
|
return false;
|
||||||
|
fprintf(F, "%d", getpid());
|
||||||
|
fclose(F);
|
||||||
|
return true;
|
||||||
|
}
|
12
tpws/sec.h
Normal file
12
tpws/sec.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/capability.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool setpcap(uint64_t caps);
|
||||||
|
int getmaxcap();
|
||||||
|
bool dropcaps();
|
||||||
|
bool droproot(uid_t uid, gid_t gid);
|
||||||
|
void daemonize();
|
||||||
|
bool writepid(const char *filename);
|
127
tpws/tpws.c
127
tpws/tpws.c
@ -20,8 +20,6 @@
|
|||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/capability.h>
|
|
||||||
#include <sys/prctl.h>
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -29,6 +27,7 @@
|
|||||||
#include "tpws_conn.h"
|
#include "tpws_conn.h"
|
||||||
#include "hostlist.h"
|
#include "hostlist.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
#include "sec.h"
|
||||||
|
|
||||||
struct params_s params;
|
struct params_s params;
|
||||||
|
|
||||||
@ -422,128 +421,6 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void daemonize()
|
|
||||||
{
|
|
||||||
int pid,fd;
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid == -1)
|
|
||||||
{
|
|
||||||
perror("fork: ");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
else if (pid != 0)
|
|
||||||
exit(0);
|
|
||||||
|
|
||||||
if (setsid() == -1)
|
|
||||||
exit(2);
|
|
||||||
if (chdir("/") == -1)
|
|
||||||
exit(2);
|
|
||||||
close(STDIN_FILENO);
|
|
||||||
close(STDOUT_FILENO);
|
|
||||||
close(STDERR_FILENO);
|
|
||||||
/* redirect fd's 0,1,2 to /dev/null */
|
|
||||||
open("/dev/null", O_RDWR);
|
|
||||||
/* stdin */
|
|
||||||
fd=dup(0);
|
|
||||||
/* stdout */
|
|
||||||
fd=dup(0);
|
|
||||||
/* stderror */
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool setpcap(cap_value_t *caps,int ncaps)
|
|
||||||
{
|
|
||||||
cap_t capabilities;
|
|
||||||
|
|
||||||
if (!(capabilities = cap_init()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ncaps && (cap_set_flag(capabilities, CAP_PERMITTED, ncaps, caps, CAP_SET) ||
|
|
||||||
cap_set_flag(capabilities, CAP_EFFECTIVE, ncaps, caps, CAP_SET)))
|
|
||||||
{
|
|
||||||
cap_free(capabilities);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (cap_set_proc(capabilities))
|
|
||||||
{
|
|
||||||
cap_free(capabilities);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cap_free(capabilities);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
static int getmaxcap()
|
|
||||||
{
|
|
||||||
int maxcap = CAP_LAST_CAP;
|
|
||||||
FILE *F = fopen("/proc/sys/kernel/cap_last_cap","r");
|
|
||||||
if (F)
|
|
||||||
{
|
|
||||||
int n=fscanf(F,"%d",&maxcap);
|
|
||||||
fclose(F);
|
|
||||||
}
|
|
||||||
return maxcap;
|
|
||||||
|
|
||||||
}
|
|
||||||
static bool dropcaps()
|
|
||||||
{
|
|
||||||
// must have CAP_SETPCAP at the end. its required to clear bounding set
|
|
||||||
cap_value_t cap_values[] = {CAP_SETPCAP};
|
|
||||||
int capct=sizeof(cap_values)/sizeof(*cap_values);
|
|
||||||
int maxcap = getmaxcap();
|
|
||||||
|
|
||||||
if (setpcap(cap_values, capct))
|
|
||||||
{
|
|
||||||
for(int cap=0;cap<=maxcap;cap++)
|
|
||||||
{
|
|
||||||
if (cap_drop_bound(cap))
|
|
||||||
{
|
|
||||||
fprintf(stderr,"could not drop cap %d\n",cap);
|
|
||||||
perror("cap_drop_bound");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// now without CAP_SETPCAP
|
|
||||||
if (!setpcap(cap_values, capct - 1))
|
|
||||||
{
|
|
||||||
perror("setpcap");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
static bool droproot()
|
|
||||||
{
|
|
||||||
if (params.uid || params.gid)
|
|
||||||
{
|
|
||||||
if (prctl(PR_SET_KEEPCAPS, 1L))
|
|
||||||
{
|
|
||||||
perror("prctl(PR_SET_KEEPCAPS): ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (setgid(params.gid))
|
|
||||||
{
|
|
||||||
perror("setgid: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (setuid(params.uid))
|
|
||||||
{
|
|
||||||
perror("setuid: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dropcaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool writepid(const char *filename)
|
|
||||||
{
|
|
||||||
FILE *F;
|
|
||||||
if (!(F=fopen(filename,"w")))
|
|
||||||
return false;
|
|
||||||
fprintf(F,"%d",getpid());
|
|
||||||
fclose(F);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool find_listen_addr(struct sockaddr_storage *salisten, bool bindll, int *if_index)
|
static bool find_listen_addr(struct sockaddr_storage *salisten, bool bindll, int *if_index)
|
||||||
@ -806,7 +683,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
set_ulimit();
|
set_ulimit();
|
||||||
|
|
||||||
if (!droproot())
|
if (!droproot(params.uid,params.gid))
|
||||||
{
|
{
|
||||||
goto exiterr;
|
goto exiterr;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user