Chinese network is notorious for its unpredictability and counter-productivity.
Most of the content are borrowed from Arch wiki and elsewhere and are only applicable to Linux.
Configuring HTTP Proxies for Docker
There are two parts to configuring Docker to use an HTTP proxy: Configuring the Docker daemon and configuring Docker containers.
Docker daemon proxy configuration
See Docker documentation on configuring Docker daemon to use HTTP proxies.
Basically, your /etc/docker/daemon.json
should be something like this:
{
"proxies": {
"http-proxy": "http://172.17.0.1:4099",
"https-proxy": "http://172.17.0.1:4099",
"no-proxy": "*.test.example.com,.example.org,127.0.0.0/8"
}
}
Docker container proxy configuration
See Docker documentation on configuring proxies for information on how to automatically configure proxies for all containers created using the docker
CLI.
Basically, your ~/.docker/config.json
should be like:
{
"proxies": {
"default": {
"httpProxy": "http://172.17.0.1:4099",
"httpsProxy": "http://172.17.0.1:4099",
"noProxy": "192.168.1.1/16,127.0.0.0/8"
}
}
}
And your http proxy should listen on the IP (172.17.0.1
in this case) of interface docker0
or simply 0.0.0.0
. Make sure your firewall does not block the port. Note that in most cases, the url for “httpsProxy” should start with http
instead of https
unless you know what you are doing.
Check whether it works by running a curl container:
docker run --rm curlimages/curl:8.11.0 -L -v http://g.co
If your docker0
IP is different than above, you can take a look at a more adaptive method at: Docker container, how to use host proxy - Stack Overflow
Convert Socks5 to http proxy
As you can see from the config above, Docker container and daemon’s proxy should be HTTP(s) proxy, while most modern proxy software only provide SOCKS5 proxy.
You can use multiple open source tools available, such as cvtp:
cvtp -listen=all -from=127.0.0.1:7891
When you don’t want the proxy, you can bypass it easily:
cvtp -listen=all -from=127.0.0.1:7891 -bypass
Configuring System Level Proxy
Tools like proxychains
, graftcp, iptables based transparent proxy e.g.g ss-tproxy won’t work with Docker.
You can use tun2socks and add --net=host
to docker run
. The steps can be something like:
# check original route table
ip a
ip r
# set physical gateway
nic=eno145
gateway=10.184.17.1
# add the IP aboard that your proxy software is connecting to direct route:
ip route add X.X.X.X/32 via $gateway dev $nic metric 1
# add tun nic
ip tuntap add mode tun dev tun0
ip addr add 198.18.0.1/15 dev tun0
ip link set dev tun0 up
# start socks5 to tun converter
tun2socks --device tun0 --proxy socks5://127.0.0.1:XXXX -interface $nic
# dangerous especially if you are typing on a remote host
# delete the original default route and route all traffic through tun0
ip r delete default
ip route add default via 198.18.0.1 dev tun0 metric 2
## optional:
# configure sysctl
sysctl net.ipv4.conf.all.rp_filter=0
sysctl net.ipv4.conf.$nic.rp_filter=0
# check what is your public IP address now
curl https://myip.xjtu.app
Configuring DNS
If you can successfully curl -v https://1.1.1.1
but cannot curl -v https://one.one.one.one
, chances are that your DNS is done.
See Docker’s DNS documentation for the documented behavior of DNS within Docker containers and information on customizing DNS configuration. In most cases, the resolvers configured on the host are also configured in the container.
Most DNS resolvers hosted on 127.0.0.0/8
are not supported due to conflicts between the container and host network namespaces. Such resolvers are removed from the container’s /etc/resolv.conf. If this would result in an empty /etc/resolv.conf
, Google DNS is used instead.
Additionally, a special case is handled if 127.0.0.53
is the only configured nameserver. In this case, Docker assumes the resolver is systemd-resolved and uses the upstream DNS resolvers from /run/systemd/resolve/resolv.conf
.
If you are using a service such as dnsmasq to provide a local resolver, consider adding a virtual interface with a link local IP address in the 169.254.0.0/16
block for dnsmasq to bind to instead of 127.0.0.1
to avoid the network namespace conflict.
Basically you can use cloudflared
to listen on 0.0.0.0
:
sudo setcap 'cap_net_bind_service=+ep' cloudflared
cloudflared proxy-dns --address 0.0.0.0 --upstream https://9.9.9.9/dns-query --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query --upstream https://149.112.112.9/dns-query --upstream https://149.112.112.112/dns-query --upstream https://8.8.8.8/dns-query --upstream https://ordns.he.net/dns-query --upstream https://64.6.64.6/dns-query --upstream https://doh.cleanbrowsing.org/doh/security-filter/