Shadowsocks

Check this: https://shadowsocks.org/en/download/clients.html

NOTE:

ArchLinux and Ubuntu users: Install from your offical repo:

# pacman –S shadowsocks 
# apt install shadowsocks 

For Chinese:

中国区的iOS推荐使用Outline, 趁着现在还没被下架, 赶紧装. 直接AppStore搜索就行.

ShadowsocksR

wiki

https://github.com/iMeiji/shadowsocks_install/wiki/ShadowsocksR-%E5%8D%8F%E8%AE%AE%E6%8F%92%E4%BB%B6%E6%96%87%E6%A1%A3

linux server/client

use branch manyuser.

https://github.com/shadowsocksr-backup/shadowsocksr

ArchLinux server/client

AUR shadowsocksr

Windows Client

https://github.com/shadowsocksrr/shadowsocksr-csharp/releases

Android client

https://github.com/shadowsocksr-backup/shadowsocksr-android/releases

v2ray

https://www.v2ray.com/en/awesome/tools.html

NOTE:

Ubuntu and ArchLinux users, you can install from your offical repo:

# pacman –S v2ray 
# apt install v2ray 

OpenVPN

  • ArchLinux/Ubuntu:
# pacman –S openvpn
# apt install openvpn
  • Other Linux:

Try your package manager before refer to this webpage: https://openvpn.net/community-resources/installing-openvpn/

  • Windows:

PLEASE download OpenVPN community version!!!

https://openvpn.net/community-downloads/

Use "WINDOWS 64-BIT MSI INSTALLER" or "WINDOWS 32-BIT MSI INSTALLER"

  • Router: Use your google.

udp2raw

  • ArchLinux

pacman –S udp2raw-tunnel

ubuntu also has udp2raw in apt repo.

  • Other Linux (including router):

https://github.com/wangyu-/udp2raw-tunnel

  • Other OS (windows/MacOS/BSD):

https://github.com/wangyu-/udp2raw-multiplatform

udp-forwarder-ex

https://github.com/recolic/udp-forwarder-ex

Notice: Domain Issue

recolic.net is ALWAYS my main domain, use it if possible.

However, recolic.net has been attacked by P.R.China government since 2019.

"recolic.net" in all URL could be replaced by "recolic.cc". Only use it as a workaround if you're fucked by china Great Firewall DNS pollution attack. Read more about this: https://recolic.net/

IPLC Proxy [NO HEAVY TRAFFIC]

Please login to view information. https://git.recolic.net/root/premium-proxy

Public Proxy Nodes [All Any Heavy Traffic]

USA/California and PRC/HongKong: Shadowsocks:

ss://chacha20-ietf-poly1305:[email protected]:25551
ss://chacha20-ietf-poly1305:[email protected]:25551

Or encoded url:

ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpyZWNvbGljLmZ1Y2tpbmcuY3BjQGJhc2UudXMxMi5yZWNvbGljLmNjOjI1NTUx#RECOLIC-US12
ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpyZWNvbGljLmZ1Y2tpbmcuY3BjQGJhc2UuaGsyLnJlY29saWMuY2M6MjU1NTE#RECOLIC-HK2

Or QR code:

Failed to load QR image

Failed to load QR image

We use AEAD methods to avoid being fucked. https://shadowsocks.org/en/spec/AEAD-Ciphers.html

Download Software

Refer to this article.

View realtime node status

https://recolic.net/status

naive udp forwarder with naive encryption. copied from an unknown guy. the code style is extremely horrible but it's good enough to fuck GFW.

You should consider a better program like this: https://github.com/recolic/udp-forwarder-ex https://github.com/recolic/udp_forwarder_ng (outdated)

udpfwd.cc

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<getopt.h>
#include <unistd.h>
#include<errno.h>

#include <fcntl.h>
//#include"aes.h"

#include <sys/epoll.h>
#include <sys/wait.h>

#include<map>
#include<string>
#include<vector>
using namespace std;

map<string, string> mp;

char local_address[100], remote_address[100];
int local_port = -1, remote_port = -1;
char keya[100], keyb[100];
char iv[100];
const int buf_len = 20480;

void handler(int num) {
    int status;
    int pid;
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if (WIFEXITED(status)) {
            //printf("The child exit with code %d",WEXITSTATUS(status));
        }
    }

}
void encrypt(char * input, int len, char *key) {
    int i, j;
    //char tmp[buf_len];
    //len=len/16*16+1;
    //AES128_CBC_encrypt_buffer((uint8_t *)tmp, (uint8_t *)input, len, (uint8_t *)key, (uint8_t *)iv);
    for (i = 0, j = 0; i < len; i++, j++) {
        if (key[j] == 0)
            j = 0;
        input[i] ^= key[j];
    }
}
void decrypt(char * input, int len, char *key) {
    int i, j;
    //char tmp[buf_len];
    //len=len/16*16+1;
    //AES128_CBC_decrypt_buffer((uint8_t *)tmp, (uint8_t *)input, len, (uint8_t *)key, (uint8_t *)iv);
    //for(i=0;i<len;i++)
    //input[i]=tmp[i];
    for (i = 0, j = 0; i < len; i++, j++) {
        if (key[j] == 0)
            j = 0;
        input[i] ^= key[j];
    }
}
void setnonblocking(int sock) {
    int opts;
    opts = fcntl(sock, F_GETFL);

    if (opts < 0) {
        perror("fcntl(sock,GETFL)");
        exit(1);
    }

    opts = opts | O_NONBLOCK;
    if (fcntl(sock, F_SETFL, opts) < 0) {
        perror("fcntl(sock,SETFL,opts)");
        exit(1);
    }

}
int main(int argc, char *argv[]) {
    int i, j, k;
    int opt;
    signal(SIGCHLD, handler);

    printf("argc=%d ", argc);
    for (i = 0; i < argc; i++)
        printf("%s ", argv[i]);
    printf("\n");
    memset(keya, 0, sizeof(keya));
    memset(keyb, 0, sizeof(keyb));
    memset(iv, 0, sizeof(iv));
    strcpy(iv, "1234567890abcdef");
    if (argc == 1) {
        printf(
                "proc -l [adress:]port -r [adress:]port  [-a passwd] [-b passwd]\n");
        return -1;
    }
    int no_l = 1, no_r = 1;
    while ((opt = getopt(argc, argv, "l:r:a:b:h")) != -1) {
        //string opt_key;
        //opt_key+=opt;
        switch (opt) {
        case 'l':
            no_l = 0;
            if (strchr(optarg, ':') != 0) {
                sscanf(optarg, "%[^:]:%d", local_address, &local_port);
            } else {
                strcpy(local_address, "127.0.0.1");
                sscanf(optarg, "%d", &local_port);
            }
            break;
        case 'r':
            no_r = 0;
            if (strchr(optarg, ':') != 0) {
                //printf("in :\n");
                //printf("%s\n",optarg);
                sscanf(optarg, "%[^:]:%d", remote_address, &remote_port);
                //printf("%d\n",remote_port);
            } else {
                strcpy(remote_address, "127.0.0.1");
                sscanf(optarg, "%d", &remote_port);
            }
            break;
        case 'a':

            strcpy(keya, optarg);
            break;
        case 'b':
            strcpy(keyb, optarg);
            break;
        case 'h':
            break;
        default:
            printf("ignore unknown <%s>", optopt);
        }
    }

    if (no_l)
        printf("error: -i not found\n");
    if (no_r)
        printf("error: -o not found\n");
    if (no_l || no_r) {
        exit(-1);
    }

    struct sockaddr_in local_me, local_other;
    int local_listen_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    int yes = 1;
    setsockopt(local_listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

    char buf[buf_len];
    socklen_t slen = sizeof(sockaddr_in);
    memset(&local_me, 0, sizeof(local_me));
    local_me.sin_family = AF_INET;
    local_me.sin_port = htons(local_port);
    local_me.sin_addr.s_addr = inet_addr(local_address);
    if (bind(local_listen_fd, (struct sockaddr*) &local_me, slen) == -1) {
        printf("socket bind error");
        exit(1);
    }
    while (1) {
        socklen_t recv_len;
        if ((recv_len = recvfrom(local_listen_fd, buf, buf_len, 0,
                (struct sockaddr *) &local_other, &slen)) == -1) {
            printf("recv_from error");
            exit(1);
        }
        printf("Received packet from %s:%d\n", inet_ntoa(local_other.sin_addr),
                ntohs(local_other.sin_port));

        if (keya[0]) {
            decrypt(buf, recv_len, keya);/*recv_len-=16;*/
        }
        buf[recv_len] = 0;
        //printf("recv_len: %d\n", recv_len);
        fflush(stdout);
        //printf("Data: %s\n" , buf);
        int local_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        //local_me.sin_addr.s_addr=inet_addr("127.0.0.1");
        setsockopt(local_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
        if (bind(local_fd, (struct sockaddr*) &local_me, slen) == -1) {
            printf("socket bind error in chilld");
            exit(1);
        }
        int ret = connect(local_fd, (struct sockaddr *) &local_other, slen);//父进程替子进程做
        if (fork() == 0)                    //子
                {
            if (ret != 0) {
                printf("connect return %d @1\n", ret);
                exit(1);
            }
            close(local_listen_fd);

            struct sockaddr_in remote_me, remote_other;

            memset(&remote_other, 0, sizeof(remote_other));
            remote_other.sin_family = AF_INET;
            //printf("remote_address=%s  remote_port=%d\n",remote_address,remote_port);
            remote_other.sin_port = htons(remote_port);
            remote_other.sin_addr.s_addr = inet_addr(remote_address);
            int remote_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            ret = connect(remote_fd, (struct sockaddr *) &remote_other, slen);
            if (ret != 0) {
                printf("connect return %d @2\n", ret);
                exit(1);
            }

            if (keyb[0]) {/*recv_len+=16;*/
                encrypt(buf, recv_len, keyb);
            }
            ret = send(remote_fd, buf, recv_len, 0);
            //printf("send return %d\n", ret);
            if (ret < 0)
                exit(-1);

            setnonblocking(remote_fd);
            setnonblocking(local_fd);
            int epollfd = epoll_create1(0);
            const int max_events = 4096;
            struct epoll_event ev, events[max_events];
            if (epollfd < 0) {
                printf("epoll return %d\n", epollfd);
                exit(-1);
            }
            ev.events = EPOLLIN;
            ev.data.fd = local_fd;
            ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, local_fd, &ev);
            if (ret < 0) {
                printf("epoll_ctl return %d\n", ret);
                exit(-1);
            }
            ev.events = EPOLLIN;
            ev.data.fd = remote_fd;
            ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, remote_fd, &ev);
            if (ret < 0) {
                printf("epoll_ctl return %d\n", ret);
                exit(-1);
            }
            for (;;) {
                int nfds = epoll_wait(epollfd, events, max_events, 180 * 1000);
                if (nfds <= 0) {
                    printf("epoll_wait return %d\n", nfds);
                    exit(-1);
                }
                int n;
                for (n = 0; n < nfds; ++n) {
                    if (events[n].data.fd == local_fd) {
                        recv_len = recv(local_fd, buf, buf_len, 0);
                        if (recv_len < 0) {
                            printf("recv return %d @1", recv_len);
                            exit(1);
                        }
                        if (keya[0]) {
                            decrypt(buf, recv_len, keya);/*recv_len-=16;*/
                        }
                        buf[recv_len] = 0;
                        //printf("len %d received from [email protected]\n", recv_len);
                        //printf("%s received from [email protected]\n",buf);
                        if (keyb[0]) {/*recv_len+=16;*/
                            encrypt(buf, recv_len, keyb);
                        }
                        //printf("before send %s\n",buf);
                        ret = send(remote_fd, buf, recv_len, 0);
                        if (ret < 0) {
                            //printf("send return %d at @1", ret);
                            exit(1);
                        }
                        //printf("send return %d @1\n", ret);
                    } else if (events[n].data.fd == remote_fd) {
                        recv_len = recv(remote_fd, buf, buf_len, 0);
                        if (recv_len < 0) {
                            printf("recv return -1 @2", recv_len);
                            exit(1);
                        }
                        if (keyb[0]) {
                            decrypt(buf, recv_len, keyb);/*recv_len-=16;*/
                        }
                        buf[recv_len] = 0;
                        //printf("len %d received from [email protected]\n", recv_len);
                        //printf("%s received from [email protected]\n",buf);
                        if (keya[0]) {/*recv_len+=16*/
                            ;
                            encrypt(buf, recv_len, keya);
                        }
                        ret = send(local_fd, buf, recv_len, 0);
                        if (ret < 0) {
                            //printf("send return %d @2", ret);
                            exit(1);
                        }

                        //printf("send return %d @2\n", ret);
                    }
                }
            }
            exit(0);
        } else {
            close(local_fd);
        }
        //exit(0);
    }

    return 0;
}