Documentation ¶
Overview ¶
Continuation of [byosh] and [SimpleSNIProxy] projects.
pre-requisites ¶
To ensure that Sniproxy works correctly, it's important to have ports 80, 443, and 53 open. However, on Ubuntu, it's possible that port 53 may be in use by systemd-resolved. To disable systemd-resolved and free up the port, follow [these instructions].
If you prefer to keep systemd-resolved and just disable the built-in resolver, you can use the following command:
sed -i 's/#DNS=/DNS=9.9.9.9/; s/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf systemctl restart systemd-resolved
How to Install ¶
The simplest way to install the software is by utilizing the pre-built binaries available on the releases page. Alternatively, there are other ways to install, which include:
Using "go install" command:
go install github.com/mosajjal/sniproxy/v2@latest
Using Docker or Podman:
docker run -d --pull always -p 80:80 -p 443:443 -p 53:53/udp -v "$(pwd)/config.defaults.yaml:/tmp/config.yaml" ghcr.io/mosajjal/sniproxy:latest --config /tmp/config.yaml
Using the installer script:
bash <(curl -L https://raw.githubusercontent.com/mosajjal/sniproxy/master/install.sh)
How to Run ¶
sniproxy can be configured using a configuration file or environment variables The configuration file is a YAML file, and an example configuration file can be found under [Sample config file]. you can find the instructions for the environment variables there as well.
sniproxy [flags] Flags: -c, --config string path to YAML configuration file --defaultconfig write the default config yaml file to stdout -h, --help help for sniproxy -v, --version show version info and exit
Setting Up an SNI Proxy Using Vultr ¶
In this tutorial, we will go over the steps to set up an SNI proxy using Vultr as a service provider. This will allow you to serve multiple SSL-enabled websites from a single IP address.
Prerequisites ¶
- A Vultr account. If you don't have one, you can sign up for free using my [Vultr referal link]
## Step 1: Create a Vultr Server
First, log in to your Vultr account and click on the "Instances" tab in the top menu. Then, click the "+" button to deploy a new server.
On the "Deploy New Instance" page, select the following options:
- Choose Server: Choose "Cloud Compute" - CPU & Storage Technology: Any of the choices should work perfectly fine - Server Location: Choose the location of the server. This will affect the latency of your website, so it's a good idea to choose a location that is close to your target audience. - Server Image: Any OS listed there is supported. If you're not sure what to choose, Ubuntu is a good option - Server Size: Choose a server size that is suitable for your needs. A small or medium-sized server should be sufficient for most SNI proxy setups. Pay attention to the monthly bandwidth usage as well - "Add Auto Backups": not strictly needed for sniproxy. - "SSH Keys": choose a SSH key to facilitate logging in later on. you can always use Vultr's builtin console as well. - Server Hostname: Choose a hostname for your server. This can be any name you like. After you have selected the appropriate options, click the "Deploy Now" button to create your server.
## Step 2: Install the SNI Proxy
Once your server has been created, log in to the server using SSH or console. The root password is available under the "Overview" tab in instances list.
Ensure the firewall (firewalld, ufw or iptables) is allowing connectivity to ports 80/TCP, 443/TCP and 53/UDP. For `ufw`, allow these ports with:
sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 53/udp sudo ufw reload
once you have a shell in front of you, run the following (assuming you're on Ubuntu 22.04)
bash <(curl -L https://raw.githubusercontent.com/mosajjal/sniproxy/master/install.sh)
above script is an interactive installer, it will ask you a few questions and then install sniproxy for you. it also installs sniproxy as a systemd servers, and enables it to start on boot.
step 3: customize your configuration ¶
above wizard will set up execution arguments for sniproxy. you can edit them by running
sudo vim /opt/sniproxy/sniproxy.yaml
and edit parameters as you see fit. for example, you can add more domains to the list of domains to proxy, or change the port numbers.
[byosh]: https://github.com/mosajjal/byosh [SimpleSNIProxy]: https://github.com/ziozzang/SimpleSNIProxy [these instructions]: https://gist.github.com/zoilomora/f7d264cefbb589f3f1b1fc2cea2c844c [Vultr referal link]: https://www.vultr.com/?ref=8578601 [Sample config file]: ./config.sample.yaml
Index ¶
- func GetHostname(data []byte) (string, error)
- func GetPublicIPv4() (string, error)
- func GetPublicIPv6() (string, error)
- func RunDNS(c *Config, l zerolog.Logger)
- func RunHTTP(c *Config, bind string, l zerolog.Logger)
- func RunHTTPS(c *Config, bind string, log zerolog.Logger)
- type Config
- type DNSClient
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetHostname ¶
GetHostname :This function is basically all most folks want to invoke out of this jumble of bits. This will take an incoming TLS Client Hello (including all the fuzzy bits at the beginning of it - fresh out of the socket) and go ahead and give us the SNI Name they want.
func GetPublicIPv4 ¶
GetPublicIPv4 tries to determine the IPv4 address of the host method 1: establish a udp connection to a known DNS server and see if we can get lucky by having a non-RFC1918 address on the interface method 2: use a public HTTP service to get the public IP note that neither of these methods are bulletproof, so there is always a chance that you need to enter the public IP manually
func GetPublicIPv6 ¶
GetPublicIPv6 tries to determine the IPv6 address of the host method 1: establish a udp connection to a known DNS server and see if we can get lucky by having a non-RFC1918 address on the interface method 2: use a public HTTP service to get the public IP method 3: send a DNS query to OpenDNS to get the public IP. DISABLED note that neither of these methods are bulletproof, so there is always a chance that you need to enter the public IP manually
Types ¶
type Config ¶
type Config struct { PublicIPv4 string `yaml:"public_ipv4"` PublicIPv6 string `yaml:"public_ipv6"` UpstreamDNS string `yaml:"upstream_dns"` UpstreamDNSOverSocks5 bool `yaml:"upstream_dns_over_socks5"` UpstreamSOCKS5 string `yaml:"upstream_socks5"` BindDNSOverUDP string `yaml:"bind_dns_over_udp"` BindDNSOverTCP string `yaml:"bind_dns_over_tcp"` BindDNSOverTLS string `yaml:"bind_dns_over_tls"` BindDNSOverQuic string `yaml:"bind_dns_over_quic"` TLSCert string `yaml:"tls_cert"` TLSKey string `yaml:"tls_key"` BindHTTP string `yaml:"bind_http"` BindHTTPAdditional []string `yaml:"bind_http_additional"` BindHTTPListeners []string `yaml:"-"` // compiled list of bind_http and bind_http_additional listen addresses BindHTTPS string `yaml:"bind_https"` BindHTTPSAdditional []string `yaml:"bind_https_additional"` BindHTTPSListeners []string `yaml:"-"` // compiled list of bind_https and bind_https_additional listen addresses Interface string `yaml:"interface"` BindPrometheus string `yaml:"bind_prometheus"` AllowConnToLocal bool `yaml:"allow_conn_to_local"` Acl []acl.ACL `yaml:"-"` DnsClient DNSClient `yaml:"-"` Dialer proxy.Dialer `yaml:"-"` // list of interface source IPs; used to rotate source IPs when initializing connections SourceAddr []netip.Addr `yaml:"-"` PreferredVersion string `yaml:"preferred_version"` // ipv4 (or 4), ipv6 (or 6), ipv4only, ipv6only, any. empty (or 0) means any. // metrics RecievedHTTP metrics.Counter `yaml:"-"` ProxiedHTTP metrics.Counter `yaml:"-"` RecievedHTTPS metrics.Counter `yaml:"-"` ProxiedHTTPS metrics.Counter `yaml:"-"` RecievedDNS metrics.Counter `yaml:"-"` ProxiedDNS metrics.Counter `yaml:"-"` }
func (*Config) SetBindHTTPListeners ¶
SetBindHTTPListeners sets up a list of bind addresses for HTTP it gets the bind address from bind_http as 0.0.0.0:80 format and the additional bind addresses from bind_http_additional as a list of ports or port ranges such as 8080, 8081-8083, 8085 when this function is called, it will compile the list of bind addresses and store it in BindHTTPListeners
func (*Config) SetBindHTTPSListeners ¶
SetBindHTTPSListeners sets up a list of bind addresses for HTTPS
func (*Config) SetDNSClient ¶
SetDNSClient sets up a DNS client based on the proxy settings provided an error in this function means the application cannot continue
type DNSClient ¶
DNSClient is a wrapper around the DNS client
func NewDNSClient ¶
NewDNSClient creates a DNS Client by parsing a URI and returning the appropriate client for it URI string could look like below:
- udp://1.1.1.1:53
- udp6://[2606:4700:4700::1111]:53
- tcp://9.9.9.9:5353
- https://dns.adguard.com
- quic://dns.adguard.com:8853
- tcp-tls://dns.adguard.com:853