Ground-Zerro / Phobos Public
Code Issues Pull requests Actions Releases View on GitHub ↗
4.4 KB c
#ifndef _WG_OBFUSCATOR_H_
#define _WG_OBFUSCATOR_H_

#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include "uthash.h"
#include "socks5_proto.h"

#ifdef __linux__
#define USE_EPOLL
#endif

#ifdef USE_EPOLL
#include <sys/epoll.h>
#else
#include <poll.h>
#endif

#define WG_OBFUSCATOR_VERSION "1.2"
#define WG_OBFUSCATOR_GIT_REPO "https://github.com/ClusterM/wg-obfuscator"

#define LL_DEFAULT      LL_INFO

#define BUFFER_SIZE                     65535
#define MAX_STATIC_BINDINGS             256
#define HANDSHAKE_TIMEOUT               5000
#define ITERATE_INTERVAL                1000
#define MAX_DUMMY_LENGTH_TOTAL          1024
#define MAX_DUMMY_LENGTH_HANDSHAKE      512

#define MAX_CLIENTS_DEFAULT             1024
#define IDLE_TIMEOUT_DEFAULT            300000
#define MAX_DUMMY_LENGTH_DATA_DEFAULT   4

#define MEDIA_PAYLOAD_TYPE_DEFAULT      0
#define MEDIA_TS_STEP_DEFAULT           0
#define MEDIA_SSRC_DEFAULT              0
#define MEDIA_OBFUSCATE_BYTES_DEFAULT   16

#define DEFAULT_INSTANCE_NAME   "main"
#define LL_ERROR        0
#define LL_WARN         1
#define LL_INFO         2
#define LL_DEBUG        3
#define LL_TRACE        4

#define log(level, fmt, ...) { if (verbose >= (level))       \
    fprintf(stderr, "[%s][%c] " fmt "\n", section_name,      \
    (                                                               \
          (level) == LL_ERROR ? 'E'                                 \
        : (level) == LL_WARN  ? 'W'                                 \
        : (level) == LL_INFO  ? 'I'                                 \
        : (level) == LL_DEBUG ? 'D'                                 \
        : (level) == LL_TRACE ? 'T'                                 \
        : '?'                                                       \
    ), ##__VA_ARGS__);                                              \
}
#define trace(fmt, ...) if (verbose >= LL_TRACE) fprintf(stderr, fmt, ##__VA_ARGS__)
#define serror_level(level, fmt, ...) log(level, fmt " - %s (%d)", ##__VA_ARGS__, strerror(errno), errno)
#define serror(fmt, ...) serror_level(LL_ERROR, fmt, ##__VA_ARGS__)

typedef enum {
    DIR_CLIENT_TO_SERVER = 0,
    DIR_SERVER_TO_CLIENT = 1,
} direction_t;

typedef enum {
    MODE_WIREGUARD = 0,
    MODE_SOCKS5 = 1,
} obfuscation_mode_t;

typedef enum {
    S5_ROLE_RELAY = 0,
    S5_ROLE_CLIENT = 1,
    S5_ROLE_SERVER = 2,
} socks5_role_t;

struct masking_handler;
typedef struct masking_handler masking_handler_t;

typedef struct {
    struct in_addr client_ip;
    uint16_t remote_port;
    uint16_t local_port;
} static_binding_t;

// A single RFC1929 username/password pair accepted by a SOCKS5 role=server
// instance. Populated from --socks5-users; checked against real SOCKS5
// USERNAME/PASSWORD subnegotiation frames terminated by the server itself.
#define MAX_SOCKS5_USERS 2048
typedef struct {
    char login[S5_CRED_MAX];
    uint8_t login_len;
    char password[S5_CRED_MAX];
    uint8_t password_len;
} socks5_cred_t;

typedef struct {
    obfuscation_mode_t mode;
    int listen_port;
    char forward_host_port[256];
    char xor_key[256];
    char client_interface[256];
    char static_bindings[10 * 1024];
    static_binding_t static_specs[MAX_STATIC_BINDINGS];
    int static_spec_count;
    int max_clients;
    long idle_timeout;
    int max_dummy_length_data;
    int obfuscate_bytes;
    uint32_t fwmark;
    int threads;
    masking_handler_t *masking_handler;
    uint8_t socks5_mask;
    uint8_t socks5_role;

    socks5_cred_t socks5_users[MAX_SOCKS5_USERS];
    int socks5_user_count;
    char socks5_stats_path[256];

    uint8_t media_payload_type;
    uint32_t media_ssrc;
    uint16_t media_ts_step;

    const volatile sig_atomic_t *stop;

    uint8_t listen_port_set;
    uint8_t forward_host_port_set;
    uint8_t xor_key_set;
    uint8_t client_interface_set;
    uint8_t static_bindings_set;
    uint8_t masking_handler_set;
} obfuscator_config_t;

typedef struct {
    struct sockaddr_in client_addr;
    int server_sock;
    masking_handler_t *masking_handler;
    uint8_t version;
    uint8_t handshaked          : 1;
    uint8_t handshake_direction : 1;
    uint8_t client_obfuscated   : 1;
    uint8_t server_obfuscated   : 1;
    uint8_t is_static           : 1;
    long last_activity_time;
    long last_handshake_request_time;
    long last_masking_timer_time;
    uint8_t masking_priv[32];
    UT_hash_handle hh;
} client_entry_t;

extern int verbose;
extern char section_name[256];

void print_version(void);

#endif