forked from qdm12/gluetun
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/FideresDev/gluetun
- Loading branch information
Showing
57 changed files
with
2,662 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
version: "3.7" | ||
|
||
services: | ||
vscode: | ||
build: . | ||
volumes: | ||
- ../:/workspace | ||
# Docker socket to access Docker server | ||
- /var/run/docker.sock:/var/run/docker.sock | ||
# SSH directory for Linux, OSX and WSL | ||
# On Linux and OSX, a symlink /mnt/ssh <-> ~/.ssh is | ||
# created in the container. On Windows, files are copied | ||
# from /mnt/ssh to ~/.ssh to fix permissions. | ||
- ~/.ssh:/mnt/ssh | ||
# Shell history persistence | ||
- ~/.zsh_history:/root/.zsh_history | ||
# Git config | ||
- ~/.gitconfig:/root/.gitconfig | ||
environment: | ||
- TZ= | ||
cap_add: | ||
# For debugging with dlv | ||
- SYS_PTRACE | ||
- NET_ADMIN | ||
security_opt: | ||
# For debugging with dlv | ||
- seccomp:unconfined | ||
entrypoint: [ "zsh", "-c", "while sleep 1000; do :; done" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
services: | ||
gluetun: | ||
image: qmcgaw/gluetun | ||
container_name: gluetun | ||
restart: always | ||
# container_name: gluetun | ||
# line above must be uncommented to allow external containers to connect. | ||
# See https://github.com/qdm12/gluetun-wiki/blob/main/setup/connect-a-container-to-gluetun.md#external-container-to-gluetun | ||
cap_add: | ||
- NET_ADMIN | ||
environment: | ||
# See https://github.com/qdm12/gluetun-wiki/tree/main/setup#setup | ||
- VPN_SERVICE_PROVIDER=protonvpn | ||
- VPN_TYPE=openvpn | ||
# OpenVPN: | ||
- OPENVPN_USER=OyWogmLEd7jfdDP2 | ||
- OPENVPN_PASSWORD=jHR0A05NJp8RCadDfK3VDLvIK65h71i1 | ||
- FREE_ONLY=on | ||
# Wireguard: | ||
# - WIREGUARD_PRIVATE_KEY=wOEI9rqqbDwnN8/Bpp22sVz48T71vJ4fYmFWujulwUU= | ||
# - WIREGUARD_ADDRESSES=10.64.222.21/32 | ||
# Timezone for accurate log times | ||
# Server list updater | ||
# See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list | ||
- FIREWALL_OUTBOUND_SUBNETS=192.168.50.0/24 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package helpers | ||
|
||
func TCPPtrToString(tcp *bool) string { | ||
if *tcp { | ||
return "TCP" | ||
} | ||
return "UDP" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package settings | ||
|
||
import ( | ||
"net/netip" | ||
|
||
"inet.af/netaddr" | ||
) | ||
|
||
func netipAddressToNetaddrIP(address netip.Addr) (ip netaddr.IP) { | ||
if address.Is4() { | ||
return netaddr.IPFrom4(address.As4()) | ||
} | ||
return netaddr.IPFrom16(address.As16()) | ||
} | ||
|
||
func netipAddressesToNetaddrIPs(addresses []netip.Addr) (ips []netaddr.IP) { | ||
ips = make([]netaddr.IP, len(addresses)) | ||
for i := range addresses { | ||
ips[i] = netipAddressToNetaddrIP(addresses[i]) | ||
} | ||
return ips | ||
} | ||
|
||
func netipPrefixToNetaddrIPPrefix(prefix netip.Prefix) (ipPrefix netaddr.IPPrefix) { | ||
netaddrIP := netipAddressToNetaddrIP(prefix.Addr()) | ||
bits := prefix.Bits() | ||
return netaddr.IPPrefixFrom(netaddrIP, uint8(bits)) | ||
} | ||
|
||
func netipPrefixesToNetaddrIPPrefixes(prefixes []netip.Prefix) (ipPrefixes []netaddr.IPPrefix) { | ||
ipPrefixes = make([]netaddr.IPPrefix, len(prefixes)) | ||
for i := range ipPrefixes { | ||
ipPrefixes[i] = netipPrefixToNetaddrIPPrefix(prefixes[i]) | ||
} | ||
return ipPrefixes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
package settings | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net/netip" | ||
|
||
"github.com/qdm12/dns/pkg/provider" | ||
"github.com/qdm12/dns/pkg/unbound" | ||
"github.com/qdm12/gosettings" | ||
"github.com/qdm12/gotree" | ||
) | ||
|
||
// Unbound is settings for the Unbound program. | ||
type Unbound struct { | ||
Providers []string `json:"providers"` | ||
Caching *bool `json:"caching"` | ||
IPv6 *bool `json:"ipv6"` | ||
VerbosityLevel *uint8 `json:"verbosity_level"` | ||
VerbosityDetailsLevel *uint8 `json:"verbosity_details_level"` | ||
ValidationLogLevel *uint8 `json:"validation_log_level"` | ||
Username string `json:"username"` | ||
Allowed []netip.Prefix `json:"allowed"` | ||
} | ||
|
||
func (u *Unbound) setDefaults() { | ||
if len(u.Providers) == 0 { | ||
u.Providers = []string{ | ||
provider.Cloudflare().String(), | ||
} | ||
} | ||
|
||
u.Caching = gosettings.DefaultPointer(u.Caching, true) | ||
u.IPv6 = gosettings.DefaultPointer(u.IPv6, false) | ||
|
||
const defaultVerbosityLevel = 1 | ||
u.VerbosityLevel = gosettings.DefaultPointer(u.VerbosityLevel, defaultVerbosityLevel) | ||
|
||
const defaultVerbosityDetailsLevel = 0 | ||
u.VerbosityDetailsLevel = gosettings.DefaultPointer(u.VerbosityDetailsLevel, defaultVerbosityDetailsLevel) | ||
|
||
const defaultValidationLogLevel = 0 | ||
u.ValidationLogLevel = gosettings.DefaultPointer(u.ValidationLogLevel, defaultValidationLogLevel) | ||
|
||
if u.Allowed == nil { | ||
u.Allowed = []netip.Prefix{ | ||
netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 0), | ||
netip.PrefixFrom(netip.AddrFrom16([16]byte{}), 0), | ||
} | ||
} | ||
|
||
u.Username = gosettings.DefaultString(u.Username, "root") | ||
} | ||
|
||
var ( | ||
ErrUnboundVerbosityLevelNotValid = errors.New("Unbound verbosity level is not valid") | ||
ErrUnboundVerbosityDetailsLevelNotValid = errors.New("Unbound verbosity details level is not valid") | ||
ErrUnboundValidationLogLevelNotValid = errors.New("Unbound validation log level is not valid") | ||
) | ||
|
||
func (u Unbound) validate() (err error) { | ||
for _, s := range u.Providers { | ||
_, err := provider.Parse(s) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
const maxVerbosityLevel = 5 | ||
if *u.VerbosityLevel > maxVerbosityLevel { | ||
return fmt.Errorf("%w: %d must be between 0 and %d", | ||
ErrUnboundVerbosityLevelNotValid, | ||
*u.VerbosityLevel, | ||
maxVerbosityLevel) | ||
} | ||
|
||
const maxVerbosityDetailsLevel = 4 | ||
if *u.VerbosityDetailsLevel > maxVerbosityDetailsLevel { | ||
return fmt.Errorf("%w: %d must be between 0 and %d", | ||
ErrUnboundVerbosityDetailsLevelNotValid, | ||
*u.VerbosityDetailsLevel, | ||
maxVerbosityDetailsLevel) | ||
} | ||
|
||
const maxValidationLogLevel = 2 | ||
if *u.ValidationLogLevel > maxValidationLogLevel { | ||
return fmt.Errorf("%w: %d must be between 0 and %d", | ||
ErrUnboundValidationLogLevelNotValid, | ||
*u.ValidationLogLevel, maxValidationLogLevel) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (u Unbound) copy() (copied Unbound) { | ||
return Unbound{ | ||
Providers: gosettings.CopySlice(u.Providers), | ||
Caching: gosettings.CopyPointer(u.Caching), | ||
IPv6: gosettings.CopyPointer(u.IPv6), | ||
VerbosityLevel: gosettings.CopyPointer(u.VerbosityLevel), | ||
VerbosityDetailsLevel: gosettings.CopyPointer(u.VerbosityDetailsLevel), | ||
ValidationLogLevel: gosettings.CopyPointer(u.ValidationLogLevel), | ||
Username: u.Username, | ||
Allowed: gosettings.CopySlice(u.Allowed), | ||
} | ||
} | ||
|
||
func (u *Unbound) mergeWith(other Unbound) { | ||
u.Providers = gosettings.MergeWithSlice(u.Providers, other.Providers) | ||
u.Caching = gosettings.MergeWithPointer(u.Caching, other.Caching) | ||
u.IPv6 = gosettings.MergeWithPointer(u.IPv6, other.IPv6) | ||
u.VerbosityLevel = gosettings.MergeWithPointer(u.VerbosityLevel, other.VerbosityLevel) | ||
u.VerbosityDetailsLevel = gosettings.MergeWithPointer(u.VerbosityDetailsLevel, other.VerbosityDetailsLevel) | ||
u.ValidationLogLevel = gosettings.MergeWithPointer(u.ValidationLogLevel, other.ValidationLogLevel) | ||
u.Username = gosettings.MergeWithString(u.Username, other.Username) | ||
u.Allowed = gosettings.MergeWithSlice(u.Allowed, other.Allowed) | ||
} | ||
|
||
func (u *Unbound) overrideWith(other Unbound) { | ||
u.Providers = gosettings.OverrideWithSlice(u.Providers, other.Providers) | ||
u.Caching = gosettings.OverrideWithPointer(u.Caching, other.Caching) | ||
u.IPv6 = gosettings.OverrideWithPointer(u.IPv6, other.IPv6) | ||
u.VerbosityLevel = gosettings.OverrideWithPointer(u.VerbosityLevel, other.VerbosityLevel) | ||
u.VerbosityDetailsLevel = gosettings.OverrideWithPointer(u.VerbosityDetailsLevel, other.VerbosityDetailsLevel) | ||
u.ValidationLogLevel = gosettings.OverrideWithPointer(u.ValidationLogLevel, other.ValidationLogLevel) | ||
u.Username = gosettings.OverrideWithString(u.Username, other.Username) | ||
u.Allowed = gosettings.OverrideWithSlice(u.Allowed, other.Allowed) | ||
} | ||
|
||
func (u Unbound) ToUnboundFormat() (settings unbound.Settings, err error) { | ||
providers := make([]provider.Provider, len(u.Providers)) | ||
for i := range providers { | ||
providers[i], err = provider.Parse(u.Providers[i]) | ||
if err != nil { | ||
return settings, err | ||
} | ||
} | ||
|
||
const port = 53 | ||
|
||
return unbound.Settings{ | ||
ListeningPort: port, | ||
IPv4: true, | ||
Providers: providers, | ||
Caching: *u.Caching, | ||
IPv6: *u.IPv6, | ||
VerbosityLevel: *u.VerbosityLevel, | ||
VerbosityDetailsLevel: *u.VerbosityDetailsLevel, | ||
ValidationLogLevel: *u.ValidationLogLevel, | ||
AccessControl: unbound.AccessControlSettings{ | ||
Allowed: netipPrefixesToNetaddrIPPrefixes(u.Allowed), | ||
}, | ||
Username: u.Username, | ||
}, nil | ||
} | ||
|
||
var ( | ||
ErrConvertingNetip = errors.New("converting net.IP to netip.Addr failed") | ||
) | ||
|
||
func (u Unbound) GetFirstPlaintextIPv4() (ipv4 netip.Addr, err error) { | ||
s := u.Providers[0] | ||
provider, err := provider.Parse(s) | ||
if err != nil { | ||
return ipv4, err | ||
} | ||
|
||
ip := provider.DNS().IPv4[0] | ||
ipv4, ok := netip.AddrFromSlice(ip) | ||
if !ok { | ||
return ipv4, fmt.Errorf("%w: for ip %s (%#v)", | ||
ErrConvertingNetip, ip, ip) | ||
} | ||
return ipv4.Unmap(), nil | ||
} | ||
|
||
func (u Unbound) String() string { | ||
return u.toLinesNode().String() | ||
} | ||
|
||
func (u Unbound) toLinesNode() (node *gotree.Node) { | ||
node = gotree.New("Unbound settings:") | ||
|
||
authServers := node.Appendf("Authoritative servers:") | ||
for _, provider := range u.Providers { | ||
authServers.Appendf(provider) | ||
} | ||
|
||
node.Appendf("Caching: %s", gosettings.BoolToYesNo(u.Caching)) | ||
node.Appendf("IPv6: %s", gosettings.BoolToYesNo(u.IPv6)) | ||
node.Appendf("Verbosity level: %d", *u.VerbosityLevel) | ||
node.Appendf("Verbosity details level: %d", *u.VerbosityDetailsLevel) | ||
node.Appendf("Validation log level: %d", *u.ValidationLogLevel) | ||
node.Appendf("System user: %s", u.Username) | ||
|
||
allowedNetworks := node.Appendf("Allowed networks:") | ||
for _, network := range u.Allowed { | ||
allowedNetworks.Appendf(network.String()) | ||
} | ||
|
||
return node | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package settings | ||
|
||
import ( | ||
"encoding/json" | ||
"net/netip" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Test_Unbound_JSON(t *testing.T) { | ||
t.Parallel() | ||
|
||
settings := Unbound{ | ||
Providers: []string{"cloudflare"}, | ||
Caching: boolPtr(true), | ||
IPv6: boolPtr(false), | ||
VerbosityLevel: uint8Ptr(1), | ||
VerbosityDetailsLevel: nil, | ||
ValidationLogLevel: uint8Ptr(0), | ||
Username: "user", | ||
Allowed: []netip.Prefix{ | ||
netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 0), | ||
netip.PrefixFrom(netip.AddrFrom16([16]byte{}), 0), | ||
}, | ||
} | ||
|
||
b, err := json.Marshal(settings) | ||
require.NoError(t, err) | ||
|
||
const expected = `{"providers":["cloudflare"],"caching":true,"ipv6":false,` + | ||
`"verbosity_level":1,"verbosity_details_level":null,"validation_log_level":0,` + | ||
`"username":"user","allowed":["0.0.0.0/0","::/0"]}` | ||
|
||
assert.Equal(t, expected, string(b)) | ||
|
||
var resultSettings Unbound | ||
err = json.Unmarshal(b, &resultSettings) | ||
require.NoError(t, err) | ||
|
||
assert.Equal(t, settings, resultSettings) | ||
} |
Oops, something went wrong.