gfw-proxy is a open source software licensed under GPL-3.0 license which aims at providing a secure and lightweight solution that helps you get rid of the Great Firewall.
We've long firmly held the belief that everyone in the world should have the same equality in accessing human knowledge, as well as the ability to enjoy the Right to Internet access (see below). But very unfortunately, if you live in a country where heavy censorship and control are applied everywhere in the internet, you might fail to enjoy your proper rights. Hopefully, we create this software trying our best to give them back to you.
... all people must be able to access the Internet in order to exercise and enjoy their rights to freedom of expression and opinion and other fundamental human rights, that states have a responsibility to ensure that Internet access is broadly available, and that states may not unreasonably restrict an individual's access to the Internet.
You (client) <---(the gfw)---> Proxy Server <------> Internet
All data transferring between you and your proxy server are encrypted (with modern tls1.3 protocol) and look similar to very normal https (http + tls) traffic as long as you send them to port 443 on proxy server.
To receive service from your proxy server, you need to provide a password to help the server identify you from other normal https traffic. If the authorization process fails, you'll be redirect to another real http server and the proxy server acts like a real https server (thus the firewall will be unlikely to block your server because it looks like a normal https server providing usual services).
To get the software working, you need to set up on both server side and client side, if didn't yet have any experience in configuring an application, don't worry, the rest of the passage will show you how to do so step by step.
Introduction:
To get the server working, you'll need...
-
a host (server) running linux (I suggest debian for its great stability, but anything else is ok) located somewhere not affected by the firewall (has full internet access), you can buy one from any virtual private server (VPS) provider
-
working local http server
-
[optional] a domain name (this is not necessary, if you don't have one, don't worry)
-
proper x509 certificate used to encrypt and verify data (also no need to worry if you haven't heard about it)
-
your great patience and sufficient time (the most important)
This is quite easy to do. All you have to do is to install one. For me, I prefer nginx, so I'll show you how to install it here.
Now I suppose you've successfully logged into your vps (via ssh, for example).
- You need to install nginx using the following command:
sudo apt update && sudo apt install -y nginx
if it says something like apt command not found
, you're probably using centOS/fodera or some other distros using dnf
as its package manager, in this case, try
sudo dnf install nginx
if this doesn't work either, you'd better use your search engine to figure out how to install nginx in your linux distribution.
- start your nginx by issuing
sudo systemctl enable --now nginx
- check if your http server is working by
sudo lsof -i:80
if you get an error message like lsof command not found
, install it by replace 'nginx' in step 1 with 'lsof', use search engine if you need help.
if everything works well, you'll get some output says nginx is listening on port 80. But if you got nothing, your http server is not running, go back and check what's wrong.
Instead of teaching how to get a certificate from a public ca (certificate authority), I'll show you how to create your own one trusted by yourself.
-
get a place to store the certificates
mkdir ~/certs && cd ~/certs
-
create ca
-
create ca private key
openssl genrsa -out rootCA.key 4096
-
create root ca certificate
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt
you need to answer some questions, if you don't know what to fill with, a simple
.
helps.
-
-
create your certificate
-
get a place to store your certificates and private key
mkdir ~/certs/my_certs && cd ~/certs/my_certs
-
create your certificate key
openssl genrsa -out my_domain.key 4096
-
create your csr (certificate signing request) file
NOTE: You only need to to choose ONE way out of the following 2.
-
if you have a subdomain name associate with your vps, use this way (replace <FILL_ME_WITH_YOUR_DNS_NAME> with your real domain name (there're 2 places))
openssl req -new -sha256 \ -key my_domain.key \ -subj "/CN=<FILL_ME_WITH_YOUR_DNS_NAME>" \ -reqexts v3_req \ -config <(cat /etc/ssl/openssl.cnf <(printf "\n[v3_req]\nextendedKeyUsage=serverAuth, clientAuth\nsubjectAltName=DNS:<FILL_ME_WITH_YOUR_DNS_NAME>")) \ -out my_domain.csr
-
if you do NOT have a domain name, it's possible to create your certificate directly with the public IP address (replace <FILL_ME_WITH_YOUR_IP_ADDRESS> with your public IP address (there're 2 places))
openssl req -new -sha256 \ -key my_domain.key \ -subj "/CN=<FILL_ME_WITH_YOUR_IP_ADDRESS>" \ -reqexts v3_req \ -config <(cat /etc/ssl/openssl.cnf <(printf "\n[v3_req]\nextendedKeyUsage=serverAuth, clientAuth\nsubjectAltName=IP:<FILL_ME_WITH_YOUR_IP_ADDRESS>")) \ -out my_domain.csr
-
-
use ca's private key to sign the request you just created, generating the certificate
NOTE: You only need to to choose ONE way out of the following 2, and this way should be the SAME as you chose in the previous step
-
if you have a subdomain name associate with your vps, use this way (replace <FILL_ME_WITH_YOUR_DNS_NAME> with your real domain name (there's 1 place))
openssl x509 -req \ -extfile <(printf "[v3_req]\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=DNS:<FILL_ME_WITH_YOUR_DNS_NAME>") -extensions v3_req -days 360 -in my_domain.csr -CA ../rootCA.crt -CAkey ../rootCA.key \ -CAcreateserial -out my_domain.crt -sha256
-
if you use your IP address in the previous step, use the following code (replace <FILL_ME_WITH_YOUR_IP_ADDRESS> with your public IP address (there's 1 place))
openssl x509 -req \ -extfile <(printf "[v3_req]\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=IP:<FILL_ME_WITH_YOUR_IP_ADDRESS>") -extensions v3_req -days 360 -in my_domain.csr -CA ../rootCA.crt -CAkey ../rootCA.key \ -CAcreateserial -out my_domain.crt -sha256
-
-
-
verify your certificates you've created so far
Now you'll need to review what's been done so far. By typing
ls
in the command line, you should see the the directory containing the following stuffs:-
my_domain.key
this is your private key, remember path to it, you'll need it later -
my_domain.csr
this is your csr file, you don't need it anymore -
my_domain.crt
this is your certificate, remember path to it, you'll need it later
-
get a place to store the file
mkdir ~/gfw_proxy && cd ~/gfw_proxy
-
use wget to get the server executable file
wget https://github.com/lry127/gfw_proxy/releases/download/v0.1-ga.1/linux-amd64.tar.gz
-
extract the runnable
tar xf ./linux-amd64.tar.gz
-
verify the software's working
./gfw_proxy
if it works, it should output the following things
usage: gfw-proxy <path_to_configure_file>
otherwise, it's not working, use a search engine to see what's wrong
-
Replace the following things in "<>"
{ "run_type": "server", "password": "<YOUR_PASSWORD>", "certificate_path": "<PATH_TO_CERTIFICATE>", "private_key": "<PATH_TO_CERTIFICATE_KEY>", "listening_address": "0.0.0.0", "listening_port": 443, "http_service_address": "localhost", "http_service_port": 80 }
-
<YOUR_PASSWORD>: your password
-
<PATH_TO_CERTIFICATE>: where your certificate is stored, if you follow the guide strictly, you can see where it's located at by this command (you should copy the output)
ls $HOME/certs/my_certs/my_domain.crt
-
<PATH_TO_CERTIFICATE_KEY>: where your private key is stored, if you follow the guide strictly, you can see where it's located at by this command (you should copy the output)
ls $HOME/certs/my_certs/my_domain.key
-
-
The sample config file might look like this:
{ "run_type": "server", "password": "U35RY3KyMnhl", "certificate_path": "/root/certs/my_certs/my_domain.crt", "private_key": "/root/certs/my_certs/my_domain.key", "listening_address": "0.0.0.0", "listening_port": 443, "http_service_address": "localhost", "http_service_port": 80 }
-
now write the config to a file called
server.json
echo "{ \"run_type\": \"server\", \"password\": \"U35RY3KyMnhl\", \"certificate_path\": \"/root/certs/my_certs/my_domain.crt\", \"private_key\": \"/root/certs/my_certs/my_domain.key\", \"listening_address\": \"0.0.0.0\", \"listening_port\": 443, \"http_service_address\": \"localhost\", \"http_service_port\": 80 }" > server.json
-
run the server:
sudo ./gfw_proxy ./server.json
if it's working, you might get the following output:
gfw-proxy start running... run type: server listening on: 0.0.0.0:443 using costum certificate: /root/certs/my_certs/my_domain.pem using costum private key: /root/certs/my_certs/my_domain.key fallback http service is running on: localhost:80
then you're DONE! CONGRATULATIONS!
-
now you'll need to run the server in background and you can safely disconnect from your ssh server. First press
CTRL+C
, then type:sudo nohup ./gfw_proxy ./server.json &
-
verify it:
sudo lsof -i:443
you'll expect it output something
-
-
Introduction:
To get the client run, all you need are merely a configuration file telling the program about your server and the root CA you just created.
There are many methods available to you to get the root ca file, if you know how to do so, just get it and skip this step.
-
Getting it using scp (supposing you're using root account)
scp root@<MY_IP_OR_DOMAIN>:~/certs/rootCA.crt .
-
Getting it using https (please first connect to your server)
cp ~/certs/rootCA.crt /var/www/html chmod 644 /var/www/html/rootCA.crt
now you can get it using your browser:
https://<MY_IP_OR_DOMAIN>/rootCA.crt
you may need to ignore warnings your browser complaining about, it's normal.
-
please download here. (suppose you're using 64 bit Windows operating system)
-
after downloading the .zip file, unzip it. (you need to right click the file and select Extract All...)
-
now we call the folder you extracted from previous step
gfw-proxy
-
create a plain text file (.txt), rename it to
client.txt
(orclient.json
if you know how to modify the postfix of a file, it doesn't matter, but you need to remember the name) -
open the file you just created
-
add the following fields, make sure they match the server configuration file
{ "run_type": "client", "password": "<YOUR_PASSWORD>", "listening_address": "0.0.0.0", "listening_port": 10080, "server_address": "<YOUR_SERVER_ADDRESS(IP OR DOMAIN NAME)>", "server_port": 443, "ca_path": "./rootCA.crt" }
-
copy the rootCA.crt file you got from Step 1 to the same folder as the executable file and configuration file.
-
enter the gfw-proxy folder by double clicking the gfw-proxy
-
type
cmd
and hitEnter
on your keyboard -
type the following command:
.\gfw_proxy.exe .\client.txt
-
if it works, it should say:
gfw-proxy start running... run type: client listening on: 0.0.0.0:10080 server is running on: <DOMAIN>:<PORT> using ca file to verify server: ./rootCA.crt
-
Open your firefox browser (you can download it from the official site)
-
now type
about:preferences#general
and scroll down to the bottom, where you can seeNetwork Settings
. ClickSettings
. -
now you're DONE!! Enjoy your work!
You should first search your problems online, if you're unsure, create an issue and I'm willing to help you.
This project uses some of code from the trojan-gfw/trojan project but instead provided a http(s) proxy and uses simpler configuration file, as well as providing a much more detailed documentation (guide).