mirror of
https://github.com/ValdikSS/GoodbyeDPI.git
synced 2025-12-17 12:54:36 +03:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23babdc8fa | ||
|
|
95765f3ed9 | ||
|
|
a5b185c2a9 | ||
|
|
c9cd3ac8c7 | ||
|
|
fab9662ac9 | ||
|
|
a88ab4337e |
22
README.md
22
README.md
@@ -79,26 +79,8 @@ And for x86_64:
|
||||
|
||||
# How to install as Windows Service
|
||||
|
||||
One way is using an [srvstart](http://www.rozanski.org.uk/software) program.
|
||||
Unpack it to `goodbyedpi` directory and create 3 files:
|
||||
|
||||
*goodbyedpi.ini*
|
||||
```INI
|
||||
[GoodByeDPI]
|
||||
startup=goodbyedpi.exe
|
||||
shutdown_method=winmessage
|
||||
auto_restart=n
|
||||
```
|
||||
*srvinstall.bat*
|
||||
```Batchfile
|
||||
srvstart install GoodByeDPI -c %CD%\goodbyedpi.ini
|
||||
```
|
||||
*srvremove.bat*
|
||||
```Batchfile
|
||||
srvstart remove GoodByeDPI
|
||||
```
|
||||
Run these batch files as Administrator to install/remove service.
|
||||
Open Windows Services panel to run service or make it start automaticaly.
|
||||
Use `service_install_russia_blacklist.cmd`, `service_install_russia_blacklist_dnsredir.cmd` and `service_remove.cmd` scripts.
|
||||
Modify them according to your own needs.
|
||||
|
||||
# Similar projects
|
||||
|
||||
|
||||
48
goodbyedpi.c
48
goodbyedpi.c
@@ -11,6 +11,7 @@
|
||||
#include <getopt.h>
|
||||
#include "windivert.h"
|
||||
#include "goodbyedpi.h"
|
||||
#include "service.h"
|
||||
#include "dnsredir.h"
|
||||
#include "blackwhitelist.h"
|
||||
|
||||
@@ -20,9 +21,6 @@
|
||||
|
||||
#define MAX_FILTERS 4
|
||||
#define MAX_PACKET_SIZE 9016
|
||||
#define IPV4_HDR_LEN 20
|
||||
#define TCP_HDR_LEN 20
|
||||
#define TCP_WINDOWSIZE_OFFSET 14
|
||||
|
||||
#define DIVERT_NO_LOCALNETS_DST "(" \
|
||||
"(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and " \
|
||||
@@ -41,13 +39,13 @@
|
||||
|
||||
#define SET_HTTP_FRAGMENT_SIZE_OPTION(fragment_size) do { \
|
||||
if (!http_fragment_size) { \
|
||||
http_fragment_size = fragment_size; \
|
||||
if (http_fragment_size <= 0 || http_fragment_size > 65535) { \
|
||||
printf(fragment_size_message); \
|
||||
if (fragment_size <= 0 || fragment_size > 65535) { \
|
||||
puts(fragment_size_message); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
http_fragment_size = fragment_size; \
|
||||
} \
|
||||
else if (http_fragment_size != fragment_size) { \
|
||||
else if (http_fragment_size != (unsigned int)fragment_size) { \
|
||||
printf( \
|
||||
"WARNING: HTTP fragment size is already set to %d, not changing.\n", \
|
||||
http_fragment_size \
|
||||
@@ -55,6 +53,7 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int running_from_service = 0;
|
||||
static HANDLE filters[MAX_FILTERS];
|
||||
static int filter_num = 0;
|
||||
static const char *http10_redirect_302 = "HTTP/1.0 302 ";
|
||||
@@ -147,7 +146,7 @@ static int deinit(HANDLE handle) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void deinit_all() {
|
||||
void deinit_all() {
|
||||
for (int i = 0; i < filter_num; i++) {
|
||||
deinit(filters[i]);
|
||||
}
|
||||
@@ -216,9 +215,9 @@ static int find_header_and_get_info(const char *pktdata, int pktlen,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void change_window_size(const char *pkt, int size) {
|
||||
static inline void change_window_size(const PWINDIVERT_TCPHDR ppTcpHdr, int size) {
|
||||
if (size >= 1 && size <= 65535) {
|
||||
*(uint16_t*)(pkt + IPV4_HDR_LEN + TCP_WINDOWSIZE_OFFSET) = htons(size);
|
||||
ppTcpHdr->Window = htons(size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +245,7 @@ static PVOID find_http_method_end(const char *pkt, int http_frag, int *is_fragme
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
static const char fragment_size_message[] =
|
||||
static const char *fragment_size_message =
|
||||
"Fragment size should be in range [0 - 65535]\n";
|
||||
int i, should_reinject, should_recalc_checksum = 0;
|
||||
int opt;
|
||||
@@ -269,8 +268,8 @@ int main(int argc, char *argv[]) {
|
||||
do_http_allports = 0,
|
||||
do_host_mixedcase = 0, do_dns_redirect = 0,
|
||||
do_dns_verb = 0, do_blacklist = 0;
|
||||
int http_fragment_size = 2;
|
||||
int https_fragment_size = 2;
|
||||
unsigned int http_fragment_size = 2;
|
||||
unsigned int https_fragment_size = 2;
|
||||
uint32_t dns_addr = 0;
|
||||
uint16_t dns_port = htons(53);
|
||||
char *host_addr, *useragent_addr, *method_addr;
|
||||
@@ -280,6 +279,15 @@ int main(int argc, char *argv[]) {
|
||||
char *hdr_name_addr = NULL, *hdr_value_addr = NULL;
|
||||
int hdr_value_len;
|
||||
|
||||
if (!running_from_service && service_register(argc, argv)) {
|
||||
/* We've been called as a service. Register service
|
||||
* and exit this thread. main() would be called from
|
||||
* service.c next time.
|
||||
*/
|
||||
running_from_service = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filter_string == NULL) {
|
||||
filter_string = malloc(strlen(filter_string_template) + 1);
|
||||
strcpy(filter_string, filter_string_template);
|
||||
@@ -290,7 +298,9 @@ int main(int argc, char *argv[]) {
|
||||
if (argc == 1) {
|
||||
/* enable mode -1 by default */
|
||||
do_passivedpi = do_host = do_host_removespace \
|
||||
= do_fragment_http = do_fragment_https = 1;
|
||||
= do_fragment_http = do_fragment_https \
|
||||
= do_fragment_http_persistent \
|
||||
= do_fragment_http_persistent_nowait = 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "1234prsaf:e:mwk:n", long_options, NULL)) != -1) {
|
||||
@@ -347,7 +357,7 @@ int main(int argc, char *argv[]) {
|
||||
do_fragment_https = 1;
|
||||
https_fragment_size = atoi(optarg);
|
||||
if (https_fragment_size <= 0 || https_fragment_size > 65535) {
|
||||
printf(fragment_size_message);
|
||||
puts(fragment_size_message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
@@ -533,7 +543,9 @@ int main(int argc, char *argv[]) {
|
||||
* ack number of received packet and retransmitting missing part again,
|
||||
* but it's better to send it anyway since it eliminates one RTT.
|
||||
*/
|
||||
if (do_fragment_http_persistent && !http_req_fragmented) {
|
||||
if (do_fragment_http_persistent && !http_req_fragmented &&
|
||||
(packet_dataLen > http_fragment_size)
|
||||
) {
|
||||
ppIpHdr->Length = htons(
|
||||
ntohs(ppIpHdr->Length) -
|
||||
packet_dataLen + http_fragment_size
|
||||
@@ -658,11 +670,11 @@ int main(int argc, char *argv[]) {
|
||||
* is enabled as there could be non-HTTP data on port 80
|
||||
*/
|
||||
if (do_fragment_http && ppTcpHdr->SrcPort == htons(80)) {
|
||||
change_window_size(packet, http_fragment_size);
|
||||
change_window_size(ppTcpHdr, http_fragment_size);
|
||||
should_recalc_checksum = 1;
|
||||
}
|
||||
else if (do_fragment_https && ppTcpHdr->SrcPort != htons(80)) {
|
||||
change_window_size(packet, https_fragment_size);
|
||||
change_window_size(ppTcpHdr, https_fragment_size);
|
||||
should_recalc_checksum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,6 @@
|
||||
#else
|
||||
#define debug(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
void deinit_all();
|
||||
|
||||
83
service.c
Normal file
83
service.c
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "goodbyedpi.h"
|
||||
#include "service.h"
|
||||
|
||||
#define SERVICE_NAME "GoodbyeDPI"
|
||||
|
||||
static SERVICE_STATUS ServiceStatus;
|
||||
static SERVICE_STATUS_HANDLE hStatus;
|
||||
static int service_argc;
|
||||
static char **service_argv;
|
||||
|
||||
int service_register(int argc, char *argv[])
|
||||
{
|
||||
SERVICE_TABLE_ENTRY ServiceTable[] = {
|
||||
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main},
|
||||
{NULL, NULL}
|
||||
};
|
||||
/*
|
||||
* Save argc & argv as service_main is called with different
|
||||
* arguments, which are passed from "start" command, not
|
||||
* from the program command line.
|
||||
* We don't need this behaviour.
|
||||
*/
|
||||
service_argc = argc;
|
||||
service_argv = malloc(sizeof(void*) * argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
service_argv[i] = strdup(argv[i]);
|
||||
}
|
||||
return StartServiceCtrlDispatcher(ServiceTable);
|
||||
}
|
||||
|
||||
void service_main(int argc __attribute__((unused)),
|
||||
char *argv[] __attribute__((unused)))
|
||||
{
|
||||
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
|
||||
ServiceStatus.dwWin32ExitCode = 0;
|
||||
ServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
ServiceStatus.dwCheckPoint = 1;
|
||||
ServiceStatus.dwWaitHint = 0;
|
||||
|
||||
hStatus = RegisterServiceCtrlHandler(
|
||||
SERVICE_NAME,
|
||||
(LPHANDLER_FUNCTION)service_controlhandler);
|
||||
if (hStatus == (SERVICE_STATUS_HANDLE)0)
|
||||
{
|
||||
// Registering Control Handler failed
|
||||
return;
|
||||
}
|
||||
|
||||
SetServiceStatus(hStatus, &ServiceStatus);
|
||||
|
||||
// Calling main with saved argc & argv
|
||||
main(service_argc, service_argv);
|
||||
|
||||
if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
|
||||
// If terminated with error
|
||||
ServiceStatus.dwWin32ExitCode = 1;
|
||||
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
SetServiceStatus (hStatus, &ServiceStatus);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Control handler function
|
||||
void service_controlhandler(DWORD request)
|
||||
{
|
||||
switch(request)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP:
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
deinit_all();
|
||||
ServiceStatus.dwWin32ExitCode = 0;
|
||||
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Report current status
|
||||
SetServiceStatus (hStatus, &ServiceStatus);
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user