Personal Proxy IPv4 Input and IPv6 Output
This is the opposite of the previous post. In this scenario, we want to send a proxy server input over IPv4, but we want the output to the web to use IPv6 whenever possible. Obviously, you must have a dual-stack VPS for this to work.
We'll use Shadowsocks-Libev as the proxy software, and as in the previous post we use Socat for data transfer between IPv4 and IPv6. Our server runs Ubuntu 20.04, and we are logged in as root. Because of the way Shadowsocks works, you don't need a domain name or DNS records to get this scenario to work.
The test server for this tutorial was virtualized by KVM and had 1 GB of RAM. The free -m command indicated that 256 MB of RAM would be sufficient. The process was not tested with OpenVZ/Virtuozzo.
Before you begin, check that your server really does have outbound IPv6 connectivity. SSH into the server and ping Google's IPv6-only address:
ping6 ipv6.google.com
The Linux ping command continues running until you explicitly press Ctrl+c on your keyboard. This is in contrast to the Windows ping command, which automatically stops after four iterations.
You should get results back showing the number of milliseconds to return a response from the Google's IPv6-only server.
In the examples given in this post:
- Your PC is on IPv4 address XX.XX.XX.XX
- Your server is on IPv4 address YY.YY.YY.YY
Install and Configure Firewall
We'll use nftables for our firewall. Install and start the nftables service:
apt update && apt upgrade -y apt install nftables -y systemctl enable nftables systemctl start nftables
Edit the nftables configuration file:
vi /etc/nftables.conf
For finer-grained control and counting, we'll implement separate IPv4 and IPv6 firewall rules. In the scenario in this post, you want SSH and Shadowsocks-Libev to receive their input over IPv4.
- Replace XX.XX.XX.XX in the template below with your PC's actual IPv4 address.
- Change port 8388 to your actual choice of port for Shadowsocks-Libev IPv4 input.
table ip filter { chain input { type filter hook input priority filter; policy accept; ct state { established, related } counter packets 0 bytes 0 accept iif "lo" counter packets 0 bytes 0 accept ip protocol icmp counter packets 0 bytes 0 accept tcp dport 22 ip saddr XX.XX.XX.XX counter packets 0 bytes 0 accept tcp dport 8388 counter packets 0 bytes 0 accept counter packets 0 bytes 0 drop } chain forward { type filter hook forward priority filter; policy accept; } chain output { type filter hook output priority filter; policy accept; tcp dport 80 counter packets 0 bytes 0 accept tcp dport 443 counter packets 0 bytes 0 accept } } table ip6 filter { chain input { type filter hook input priority filter; policy accept; ct state { established, related } counter packets 0 bytes 0 accept iif "lo" counter packets 0 bytes 0 accept ip6 nexthdr ipv6-icmp counter packets 0 bytes 0 accept counter packets 0 bytes 0 drop } chain forward { type filter hook forward priority filter; policy accept; } chain output { type filter hook output priority filter; policy accept; tcp dport 80 counter packets 0 bytes 0 accept tcp dport 443 counter packets 0 bytes 0 accept } }
Save the nftables configuration file. Restart nftables with your revised configuration:
systemctl restart nftables
Install and Configure Socat
Socat is a Linux command-line utility that establishes two bidirectional byte streams and transfers data between them. We'll use Socat to convert IPv4 input on port 8388 to IPv6. Install the package:
apt install socat -y
Create the Socat systemd service file:
vi /lib/systemd/system/socat.service
Change port 8388 in the template below to your actual choice of port on which Shadowsocks-Libev will receive input:
[Unit] Description=Socat [Service] User=root ExecStart=/usr/bin/socat TCP4-LISTEN:8388,reuseaddr,fork TCP6:[::1]:8388 [Install] WantedBy=multi-user.target
Save the Socat systemd service file. Start the service:
systemctl enable socat
systemctl start socat
Install and Configure Shadowsocks-Libev
Install Shadowsocks-Libev from the Ubuntu repositories. We'll also install the Haveged random number generator. This remedies low-entropy conditions in Linux's /dev/random, thus improving the quality of encryption.
apt install haveged shadowsocks-libev -y
Edit the Shadowsocks-Libev configuration file:
vi /etc/shadowsocks-libev/config.json
- Notice that Shadowsocks-Libev listens only on IPv6 localhost.
- Change port 8388 in the template below to your actual choice of port for Shadowsocks-Libev input.
- Change the sample password to something stronger.
- Make sure you use an AEAD encryption method, as listed at shadowsocks.org. The AES ciphers work best on devices with hardware AES acceleration. Therefore we choose chacha20-ietf-poly1305 in this example for maximum flexibility.
{ "server": "::1", "server_port":8388, "local_port":1080, "password":"pass1234", "timeout":300, "method":"chacha20-ietf-poly1305", "ipv6_first": true }
Save the Shadowsocks-Libev configuration file. When you've saved the file, restart the service:
systemctl restart shadowsocks-libev
Check Shadowsocks-Libev
Here are some ways you can check that Shadowsocks-Libev is running and listening as expected:
systemctl status shadowsocks-libev journalctl -u shadowsocks-libev apt install net-tools netstat -tulpn
That last command should show:
- Socat is listening on all IPv4 interfaces port 8388.
- Shadowsocks-Libev is listening on ::1 IPv6 port 8388.
Install and Configure Client
We will use Windows as our example client. (Shadowocks clients also exist for macOS, Linux, Android, iOS, and OpenWRT.) Download the Windows client from GitHub. Unzip the downloaded zip file. Launch Shadowsocks.exe.
On the Server screen of the client, specify your server parameters, e.g.:
- Server IP = YY.YY.YY.YY
- Server Port = 8388
- Password = pass1234
- Encryption = chacha20-ietf-poly1305
Now configure your browser to use the SOCKS5 proxy listening on 127.0.0.1 port 1080. On Chrome, you can do this with the SwitchyOmega extension. On Firefox you can do this natively under Options > General > Network Settings > Settings.
Check Functionality
Visit a website known to have IPv4 and IPv6 address, e.g. https://www.google.com. It should display in your browser.
You can see that IPv6 is working at least some of the time by going to your server and checking the IPv6 output packet counts:
nft list ruleset
The IPv6 packet counts for HTTP/HTTPS should be non-zero.
For more conclusive evidence, capture 100 packets of HTTP or HTTPS:
tcpdump -i any -c100 -w web.pcap "dst port 80 or dst port 443"
Again, on your client, visit the website known to have both IPv4 and IPv6 connectivity such as https://www.google.com. A single visit should reach the 100-packet limit, so there is no need to explicitly stop tcpdump.
Display the results of the tcpdump capture:
tcpdump -nn -r web.pcap
If everything is working correctly, you should see IPv6 IP addresses.
Quit Proxy Session
When you're done browsing, quit your client's proxy session:
- Revert your browser back to its original network settings, so that it no longer expects a proxy server on port 1080.
- In the system tray, find the Shadowsocks paper airplane icon, right-click on it, and select Quit.
Comments
Great tutorial, thank you..
⭕ A simple uptime dashboard using UptimeRobot API https://upy.duo.ovh
⭕ Currently using VPS from BuyVM, GreenCloudVPS, Gullo's, Hetzner, HostHatch, InceptionHosting, LetBox, MaxKVM, MrVM, VirMach.
These tutorials might have a place on the homepage. Thanks for the guides!
AMD EPYC powered Performance NVMe VPS - Los Angeles, Dallas, New York, Amsterdam, Singapore | Support | Status
very useful, thank you
I don't want to let you down, but it can be much simpler to achieve this. Add the following line to shadowsocks-libev config file:
"ipv6_first": true
That's done. You will get ipv6 when possible.
Here is a link to the related issue on github: https://github.com/shadowsocks/shadowsocks-libev/issues/1539
Yes, the insertion of socat in front of SS is just a precaution.
CTRL+D
https://microlxc.net/index.php?p=deploy