Compare commits
4 Commits
openvpn-2.
...
ci-runs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
801c9a3086 | ||
|
|
92011205be | ||
|
|
c9707646bd | ||
|
|
c50705736b |
27
.github/workflows/ci.yml
vendored
27
.github/workflows/ci.yml
vendored
@@ -66,6 +66,33 @@ jobs:
|
|||||||
- name: Build final image
|
- name: Build final image
|
||||||
run: docker build -t final-image .
|
run: docker build -t final-image .
|
||||||
|
|
||||||
|
- name: Run Wireguard
|
||||||
|
if: |
|
||||||
|
github.repository == 'qdm12/gluetun' &&
|
||||||
|
(
|
||||||
|
github.event_name == 'push' ||
|
||||||
|
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
|
||||||
|
)
|
||||||
|
run: |
|
||||||
|
docker run -it --rm --cap-add=NET_ADMIN -e VPNSP=mullvad -e VPN_TYPE=wireguard \
|
||||||
|
-e WIREGUARD_PRIVATE_KEY=${{ secrets.WIREGUARD_PRIVATE_KEY }} \
|
||||||
|
-e WIREGUARD_ADDRESS=${{ secrets.WIREGUARD_ADDRESS }} \
|
||||||
|
final-image \
|
||||||
|
exit-once-connected
|
||||||
|
|
||||||
|
- name: Run OpenVPN
|
||||||
|
if: |
|
||||||
|
github.repository == 'qdm12/gluetun' &&
|
||||||
|
(
|
||||||
|
github.event_name == 'push' ||
|
||||||
|
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
|
||||||
|
)
|
||||||
|
run: |
|
||||||
|
docker run -it --rm --cap-add=NET_ADMIN -e VPNSP=mullvad -e VPN_TYPE=openvpn \
|
||||||
|
-e OPENVPN_PASSWORD=${{ secrets.OPENVPN_PASSWORD }} \
|
||||||
|
final-image \
|
||||||
|
exit-once-connected
|
||||||
|
|
||||||
codeql:
|
codeql:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ ENV VPN_SERVICE_PROVIDER=pia \
|
|||||||
OPENVPN_PASSWORD= \
|
OPENVPN_PASSWORD= \
|
||||||
OPENVPN_USER_SECRETFILE=/run/secrets/openvpn_user \
|
OPENVPN_USER_SECRETFILE=/run/secrets/openvpn_user \
|
||||||
OPENVPN_PASSWORD_SECRETFILE=/run/secrets/openvpn_password \
|
OPENVPN_PASSWORD_SECRETFILE=/run/secrets/openvpn_password \
|
||||||
OPENVPN_VERSION=2.4 \
|
OPENVPN_VERSION=2.6 \
|
||||||
OPENVPN_VERBOSITY=1 \
|
OPENVPN_VERBOSITY=1 \
|
||||||
OPENVPN_FLAGS= \
|
OPENVPN_FLAGS= \
|
||||||
OPENVPN_CIPHERS= \
|
OPENVPN_CIPHERS= \
|
||||||
@@ -224,9 +224,6 @@ EXPOSE 8000/tcp 8888/tcp 8388/tcp 8388/udp
|
|||||||
HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=3 CMD /gluetun-entrypoint healthcheck
|
HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=3 CMD /gluetun-entrypoint healthcheck
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN apk add --no-cache --update -l wget && \
|
RUN apk add --no-cache --update -l wget && \
|
||||||
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.12/main" openvpn\~2.4 && \
|
|
||||||
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.16/main" openssl\~1.1 && \
|
|
||||||
mv /usr/sbin/openvpn /usr/sbin/openvpn2.4 && \
|
|
||||||
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" openvpn\~2.5 && \
|
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" openvpn\~2.5 && \
|
||||||
mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \
|
mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \
|
||||||
apk del openvpn && \
|
apk del openvpn && \
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
tun Tun, netLinker netLinker, cmder RunStarter,
|
tun Tun, netLinker netLinker, cmder RunStarter,
|
||||||
cli clier,
|
cli clier,
|
||||||
) error {
|
) error {
|
||||||
|
var exitOnceConnected bool
|
||||||
if len(args) > 1 { // cli operation
|
if len(args) > 1 { // cli operation
|
||||||
switch args[1] {
|
switch args[1] {
|
||||||
case "healthcheck":
|
case "healthcheck":
|
||||||
@@ -159,6 +160,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
return cli.FormatServers(args[2:])
|
return cli.FormatServers(args[2:])
|
||||||
case "genkey":
|
case "genkey":
|
||||||
return cli.GenKey(args[2:])
|
return cli.GenKey(args[2:])
|
||||||
|
case "exit-once-connected":
|
||||||
|
exitOnceConnected = true
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%w: %s", errCommandUnknown, args[1])
|
return fmt.Errorf("%w: %s", errCommandUnknown, args[1])
|
||||||
}
|
}
|
||||||
@@ -270,7 +273,6 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
|
|
||||||
err = printVersions(ctx, logger, []printVersionElement{
|
err = printVersions(ctx, logger, []printVersionElement{
|
||||||
{name: "Alpine", getVersion: alpineConf.Version},
|
{name: "Alpine", getVersion: alpineConf.Version},
|
||||||
{name: "OpenVPN 2.4", getVersion: ovpnConf.Version24},
|
|
||||||
{name: "OpenVPN 2.5", getVersion: ovpnConf.Version25},
|
{name: "OpenVPN 2.5", getVersion: ovpnConf.Version25},
|
||||||
{name: "OpenVPN 2.6", getVersion: ovpnConf.Version26},
|
{name: "OpenVPN 2.6", getVersion: ovpnConf.Version26},
|
||||||
{name: "IPtables", getVersion: firewallConf.Version},
|
{name: "IPtables", getVersion: firewallConf.Version},
|
||||||
@@ -478,7 +480,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
controlGroupHandler.Add(httpServerHandler)
|
controlGroupHandler.Add(httpServerHandler)
|
||||||
|
|
||||||
healthLogger := logger.New(log.SetComponent("healthcheck"))
|
healthLogger := logger.New(log.SetComponent("healthcheck"))
|
||||||
healthcheckServer := healthcheck.NewServer(allSettings.Health, healthLogger, vpnLooper)
|
healthcheckServer := healthcheck.NewServer(allSettings.Health, healthLogger, vpnLooper,
|
||||||
|
exitOnceConnected)
|
||||||
healthServerHandler, healthServerCtx, healthServerDone := goshutdown.NewGoRoutineHandler(
|
healthServerHandler, healthServerCtx, healthServerDone := goshutdown.NewGoRoutineHandler(
|
||||||
"HTTP health server", goroutine.OptionTimeout(defaultShutdownTimeout))
|
"HTTP health server", goroutine.OptionTimeout(defaultShutdownTimeout))
|
||||||
go healthcheckServer.Run(healthServerCtx, healthServerDone)
|
go healthcheckServer.Run(healthServerCtx, healthServerDone)
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/klauspost/compress v1.17.11
|
github.com/klauspost/compress v1.17.11
|
||||||
github.com/klauspost/pgzip v1.2.6
|
github.com/klauspost/pgzip v1.2.6
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2
|
github.com/pelletier/go-toml/v2 v2.2.3
|
||||||
github.com/qdm12/dns/v2 v2.0.0-rc8
|
github.com/qdm12/dns/v2 v2.0.0-rc8
|
||||||
github.com/qdm12/gosettings v0.4.3
|
github.com/qdm12/gosettings v0.4.3
|
||||||
github.com/qdm12/goshutdown v0.3.0
|
github.com/qdm12/goshutdown v0.3.0
|
||||||
@@ -22,7 +22,7 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
|
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.30.0
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.27.0
|
||||||
golang.org/x/text v0.19.0
|
golang.org/x/text v0.19.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
|
|||||||
17
go.sum
17
go.sum
@@ -4,7 +4,6 @@ github.com/breml/rootcerts v0.2.18 h1:KjZaNT7AX/akUjzpStuwTMQs42YHlPyc6NmdwShVba
|
|||||||
github.com/breml/rootcerts v0.2.18/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw=
|
github.com/breml/rootcerts v0.2.18/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
@@ -42,8 +41,8 @@ github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE9
|
|||||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
@@ -74,13 +73,6 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
|
|||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||||
@@ -120,8 +112,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
@@ -150,7 +142,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
|
|||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
// OpenVPN contains settings to configure the OpenVPN client.
|
// OpenVPN contains settings to configure the OpenVPN client.
|
||||||
type OpenVPN struct {
|
type OpenVPN struct {
|
||||||
// Version is the OpenVPN version to run.
|
// Version is the OpenVPN version to run.
|
||||||
// It can only be "2.4".
|
// It can only be "2.5" or "2.6".
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
// User is the OpenVPN authentication username.
|
// User is the OpenVPN authentication username.
|
||||||
// It cannot be nil in the internal state if OpenVPN is used.
|
// It cannot be nil in the internal state if OpenVPN is used.
|
||||||
@@ -90,7 +90,7 @@ var ivpnAccountID = regexp.MustCompile(`^(i|ivpn)\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4
|
|||||||
|
|
||||||
func (o OpenVPN) validate(vpnProvider string) (err error) {
|
func (o OpenVPN) validate(vpnProvider string) (err error) {
|
||||||
// Validate version
|
// Validate version
|
||||||
validVersions := []string{openvpn.Openvpn24}
|
validVersions := []string{openvpn.Openvpn25, openvpn.Openvpn26}
|
||||||
if err = validate.IsOneOf(o.Version, validVersions...); err != nil {
|
if err = validate.IsOneOf(o.Version, validVersions...); err != nil {
|
||||||
return fmt.Errorf("%w: %w", ErrOpenVPNVersionIsNotValid, err)
|
return fmt.Errorf("%w: %w", ErrOpenVPNVersionIsNotValid, err)
|
||||||
}
|
}
|
||||||
@@ -289,7 +289,7 @@ func (o *OpenVPN) overrideWith(other OpenVPN) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *OpenVPN) setDefaults(vpnProvider string) {
|
func (o *OpenVPN) setDefaults(vpnProvider string) {
|
||||||
o.Version = gosettings.DefaultComparable(o.Version, openvpn.Openvpn24)
|
o.Version = gosettings.DefaultComparable(o.Version, openvpn.Openvpn26)
|
||||||
o.User = gosettings.DefaultPointer(o.User, "")
|
o.User = gosettings.DefaultPointer(o.User, "")
|
||||||
if vpnProvider == providers.Mullvad {
|
if vpnProvider == providers.Mullvad {
|
||||||
o.Password = gosettings.DefaultPointer(o.Password, "m")
|
o.Password = gosettings.DefaultPointer(o.Password, "m")
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||||
"github.com/qdm12/gluetun/internal/constants/providers"
|
"github.com/qdm12/gluetun/internal/constants/providers"
|
||||||
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/pprof"
|
"github.com/qdm12/gluetun/internal/pprof"
|
||||||
"github.com/qdm12/gosettings/reader"
|
"github.com/qdm12/gosettings/reader"
|
||||||
@@ -160,6 +162,18 @@ func (s Settings) Warnings() (warnings []string) {
|
|||||||
" so this will likely not work anymore. See https://github.com/qdm12/gluetun/issues/1498.")
|
" so this will likely not work anymore. See https://github.com/qdm12/gluetun/issues/1498.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if helpers.IsOneOf(s.VPN.Provider.Name, providers.SlickVPN) &&
|
||||||
|
s.VPN.Type == vpn.OpenVPN {
|
||||||
|
warnings = append(warnings, "OpenVPN 2.5 and 2.6 use OpenSSL 3 "+
|
||||||
|
"which prohibits the usage of weak security in today's standards. "+
|
||||||
|
s.VPN.Provider.Name+" uses weak security which is out "+
|
||||||
|
"of Gluetun's control so the only workaround is to allow such weaknesses "+
|
||||||
|
`using the OpenVPN option tls-cipher "DEFAULT:@SECLEVEL=0". `+
|
||||||
|
"You might want to reach to your provider so they upgrade their certificates. "+
|
||||||
|
"Once this is done, you will have to let the Gluetun maintainers know "+
|
||||||
|
"by creating an issue, attaching the new certificate and we will update Gluetun.")
|
||||||
|
}
|
||||||
|
|
||||||
// TODO remove in v4
|
// TODO remove in v4
|
||||||
if s.DNS.ServerAddress.Unmap().Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
|
if s.DNS.ServerAddress.Unmap().Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
|
||||||
warnings = append(warnings, "DNS address is set to "+s.DNS.ServerAddress.String()+
|
warnings = append(warnings, "DNS address is set to "+s.DNS.ServerAddress.String()+
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func Test_Settings_String(t *testing.T) {
|
|||||||
| | ├── Protocol: UDP
|
| | ├── Protocol: UDP
|
||||||
| | └── Private Internet Access encryption preset: strong
|
| | └── Private Internet Access encryption preset: strong
|
||||||
| └── OpenVPN settings:
|
| └── OpenVPN settings:
|
||||||
| ├── OpenVPN version: 2.4
|
| ├── OpenVPN version: 2.6
|
||||||
| ├── User: [not set]
|
| ├── User: [not set]
|
||||||
| ├── Password: [not set]
|
| ├── Password: [not set]
|
||||||
| ├── Private Internet Access encryption preset: strong
|
| ├── Private Internet Access encryption preset: strong
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package openvpn
|
package openvpn
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Openvpn24 = "2.4"
|
Openvpn25 = "2.5"
|
||||||
|
Openvpn26 = "2.6"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ type Server struct {
|
|||||||
dialer *net.Dialer
|
dialer *net.Dialer
|
||||||
config settings.Health
|
config settings.Health
|
||||||
vpn vpnHealth
|
vpn vpnHealth
|
||||||
|
exitOnceConnected bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(config settings.Health,
|
func NewServer(config settings.Health,
|
||||||
logger Logger, vpnLoop StatusApplier,
|
logger Logger, vpnLoop StatusApplier, exitOnceConnected bool,
|
||||||
) *Server {
|
) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
|||||||
13
internal/netlink/ipv6_test.go
Normal file
13
internal/netlink/ipv6_test.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package netlink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/qdm12/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_IsIPv6Supported(t *testing.T) {
|
||||||
|
n := New(log.New(log.SetLevel(log.LevelDebug)))
|
||||||
|
supported, err := n.IsIPv6Supported()
|
||||||
|
t.Log(supported, err)
|
||||||
|
}
|
||||||
@@ -13,7 +13,8 @@ import (
|
|||||||
var ErrVersionUnknown = errors.New("OpenVPN version is unknown")
|
var ErrVersionUnknown = errors.New("OpenVPN version is unknown")
|
||||||
|
|
||||||
const (
|
const (
|
||||||
binOpenvpn24 = "openvpn2.4"
|
binOpenvpn25 = "openvpn2.5"
|
||||||
|
binOpenvpn26 = "openvpn2.6"
|
||||||
)
|
)
|
||||||
|
|
||||||
func start(ctx context.Context, starter CmdStarter, version string, flags []string) (
|
func start(ctx context.Context, starter CmdStarter, version string, flags []string) (
|
||||||
@@ -21,8 +22,10 @@ func start(ctx context.Context, starter CmdStarter, version string, flags []stri
|
|||||||
) {
|
) {
|
||||||
var bin string
|
var bin string
|
||||||
switch version {
|
switch version {
|
||||||
case openvpn.Openvpn24:
|
case openvpn.Openvpn25:
|
||||||
bin = binOpenvpn24
|
bin = binOpenvpn25
|
||||||
|
case openvpn.Openvpn26:
|
||||||
|
bin = binOpenvpn26
|
||||||
default:
|
default:
|
||||||
return nil, nil, nil, fmt.Errorf("%w: %s", ErrVersionUnknown, version)
|
return nil, nil, nil, fmt.Errorf("%w: %s", ErrVersionUnknown, version)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Configurator) Version24(ctx context.Context) (version string, err error) {
|
func (c *Configurator) Version25(ctx context.Context) (version string, err error) {
|
||||||
return c.version(ctx, binOpenvpn24)
|
return c.version(ctx, binOpenvpn25)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Configurator) Version26(ctx context.Context) (version string, err error) {
|
||||||
|
return c.version(ctx, binOpenvpn26)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrVersionTooShort = errors.New("version output is too short")
|
var ErrVersionTooShort = errors.New("version output is too short")
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ func (p *Provider) OpenVPNConfig(connection models.Connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch settings.Version {
|
switch settings.Version {
|
||||||
case openvpn.Openvpn24:
|
|
||||||
providerSettings.Ciphers = []string{openvpn.AES256cbc}
|
|
||||||
case openvpn.Openvpn25, openvpn.Openvpn26:
|
case openvpn.Openvpn25, openvpn.Openvpn26:
|
||||||
providerSettings.Ciphers = []string{
|
providerSettings.Ciphers = []string{
|
||||||
openvpn.AES256gcm, openvpn.AES256cbc, openvpn.AES192gcm,
|
openvpn.AES256gcm, openvpn.AES256cbc, openvpn.AES192gcm,
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ func Test_modifyConfig(t *testing.T) {
|
|||||||
"suppress-timestamps",
|
"suppress-timestamps",
|
||||||
"auth-user-pass /etc/openvpn/auth.conf",
|
"auth-user-pass /etc/openvpn/auth.conf",
|
||||||
"verb 0",
|
"verb 0",
|
||||||
"cipher cipher", //nolint:dupword
|
"data-ciphers-fallback cipher",
|
||||||
"ncp-ciphers cipher",
|
"data-ciphers cipher",
|
||||||
"auth sha512",
|
"auth sha512",
|
||||||
"mssfix 1000",
|
"mssfix 1000",
|
||||||
"pull-filter ignore \"route-ipv6\"",
|
"pull-filter ignore \"route-ipv6\"",
|
||||||
|
|||||||
@@ -31,5 +31,11 @@ func (p *Provider) OpenVPNConfig(connection models.Connection,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SlickVPN's certificate is sha1WithRSAEncryption and sha1 is now
|
||||||
|
// rejected by openssl 3.x.x which is used by OpenVPN >= 2.5.
|
||||||
|
// We lower the security level to 3 to allow this algorithm,
|
||||||
|
// see https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html
|
||||||
|
providerSettings.TLSCipher = "DEFAULT:@SECLEVEL=0"
|
||||||
|
|
||||||
return utils.OpenVPNConfig(providerSettings, connection, settings, ipv6Supported)
|
return utils.OpenVPNConfig(providerSettings, connection, settings, ipv6Supported)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ func CipherLines(ciphers []string) (lines []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return []string{
|
return []string{
|
||||||
"cipher " + ciphers[0],
|
"data-ciphers-fallback " + ciphers[0],
|
||||||
"ncp-ciphers " + strings.Join(ciphers, ":"),
|
"data-ciphers " + strings.Join(ciphers, ":"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,16 @@ func Test_CipherLines(t *testing.T) {
|
|||||||
"empty version": {
|
"empty version": {
|
||||||
ciphers: []string{"AES"},
|
ciphers: []string{"AES"},
|
||||||
lines: []string{
|
lines: []string{
|
||||||
"cipher AES",
|
"data-ciphers-fallback AES",
|
||||||
"ncp-ciphers AES",
|
"data-ciphers AES",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"2.4": {
|
"2.5": {
|
||||||
ciphers: []string{"AES", "CBC"},
|
ciphers: []string{"AES", "CBC"},
|
||||||
version: "2.4",
|
version: "2.5",
|
||||||
lines: []string{
|
lines: []string{
|
||||||
"cipher AES",
|
"data-ciphers-fallback AES",
|
||||||
"ncp-ciphers AES:CBC",
|
"data-ciphers AES:CBC",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ package api
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,6 +20,8 @@ const (
|
|||||||
IP2Location Provider = "ip2location"
|
IP2Location Provider = "ip2location"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const echoipPrefix = "echoip#"
|
||||||
|
|
||||||
type NameToken struct {
|
type NameToken struct {
|
||||||
Name string
|
Name string
|
||||||
Token string
|
Token string
|
||||||
@@ -30,15 +36,19 @@ func New(nameTokenPairs []NameToken, client *http.Client) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parsing API name: %w", err)
|
return nil, fmt.Errorf("parsing API name: %w", err)
|
||||||
}
|
}
|
||||||
switch provider {
|
switch {
|
||||||
case Cloudflare:
|
case provider == Cloudflare:
|
||||||
fetchers[i] = newCloudflare(client)
|
fetchers[i] = newCloudflare(client)
|
||||||
case IfConfigCo:
|
case provider == IfConfigCo:
|
||||||
fetchers[i] = newIfConfigCo(client)
|
const ifConfigCoURL = "https://ifconfig.co"
|
||||||
case IPInfo:
|
fetchers[i] = newEchoip(client, ifConfigCoURL)
|
||||||
|
case provider == IPInfo:
|
||||||
fetchers[i] = newIPInfo(client, nameTokenPair.Token)
|
fetchers[i] = newIPInfo(client, nameTokenPair.Token)
|
||||||
case IP2Location:
|
case provider == IP2Location:
|
||||||
fetchers[i] = newIP2Location(client, nameTokenPair.Token)
|
fetchers[i] = newIP2Location(client, nameTokenPair.Token)
|
||||||
|
case strings.HasPrefix(string(provider), echoipPrefix):
|
||||||
|
url := strings.TrimPrefix(string(provider), echoipPrefix)
|
||||||
|
fetchers[i] = newEchoip(client, url)
|
||||||
default:
|
default:
|
||||||
panic("provider not valid: " + provider)
|
panic("provider not valid: " + provider)
|
||||||
}
|
}
|
||||||
@@ -46,20 +56,88 @@ func New(nameTokenPairs []NameToken, client *http.Client) (
|
|||||||
return fetchers, nil
|
return fetchers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var regexEchoipURL = regexp.MustCompile(`^http(s|):\/\/.+$`)
|
||||||
|
|
||||||
var ErrProviderNotValid = errors.New("API name is not valid")
|
var ErrProviderNotValid = errors.New("API name is not valid")
|
||||||
|
|
||||||
func ParseProvider(s string) (provider Provider, err error) {
|
func ParseProvider(s string) (provider Provider, err error) {
|
||||||
switch strings.ToLower(s) {
|
possibleProviders := []Provider{
|
||||||
case "cloudflare":
|
Cloudflare,
|
||||||
return Cloudflare, nil
|
IfConfigCo,
|
||||||
case string(IfConfigCo):
|
IP2Location,
|
||||||
return IfConfigCo, nil
|
IPInfo,
|
||||||
case "ipinfo":
|
|
||||||
return IPInfo, nil
|
|
||||||
case "ip2location":
|
|
||||||
return IP2Location, nil
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf(`%w: %q can only be "cloudflare", "ifconfigco", "ip2location" or "ipinfo"`,
|
|
||||||
ErrProviderNotValid, s)
|
|
||||||
}
|
}
|
||||||
|
stringToProvider := make(map[string]Provider, len(possibleProviders))
|
||||||
|
for _, provider := range possibleProviders {
|
||||||
|
stringToProvider[string(provider)] = provider
|
||||||
|
}
|
||||||
|
provider, ok := stringToProvider[strings.ToLower(s)]
|
||||||
|
if ok {
|
||||||
|
return provider, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
customPrefixToURLRegex := map[string]*regexp.Regexp{
|
||||||
|
echoipPrefix: regexEchoipURL,
|
||||||
|
}
|
||||||
|
for prefix, urlRegex := range customPrefixToURLRegex {
|
||||||
|
match, err := checkCustomURL(s, prefix, urlRegex)
|
||||||
|
if !match {
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return Provider(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
providerStrings := make([]string, 0, len(stringToProvider)+len(customPrefixToURLRegex))
|
||||||
|
for _, providerString := range slices.Sorted(maps.Keys(stringToProvider)) {
|
||||||
|
providerStrings = append(providerStrings, `"`+providerString+`"`)
|
||||||
|
}
|
||||||
|
for _, prefix := range slices.Sorted(maps.Keys(customPrefixToURLRegex)) {
|
||||||
|
providerStrings = append(providerStrings, "a custom "+prefix+" url")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf(`%w: %q can only be %s`,
|
||||||
|
ErrProviderNotValid, s, orStrings(providerStrings))
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrCustomURLNotValid = errors.New("custom URL is not valid")
|
||||||
|
|
||||||
|
func checkCustomURL(s, prefix string, regex *regexp.Regexp) (match bool, err error) {
|
||||||
|
if !strings.HasPrefix(s, prefix) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
s = strings.TrimPrefix(s, prefix)
|
||||||
|
_, err = url.Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return true, fmt.Errorf("%s %w: %w", prefix, ErrCustomURLNotValid, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if regex.MatchString(s) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, fmt.Errorf("%s %w: %q does not match regular expression: %s",
|
||||||
|
prefix, ErrCustomURLNotValid, s, regex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func orStrings(strings []string) (result string) {
|
||||||
|
return joinStrings(strings, "or")
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinStrings(strings []string, lastJoin string) (result string) {
|
||||||
|
if len(strings) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
result = strings[0]
|
||||||
|
for i := 1; i < len(strings); i++ {
|
||||||
|
if i < len(strings)-1 {
|
||||||
|
result += ", " + strings[i]
|
||||||
|
} else {
|
||||||
|
result += " " + lastJoin + " " + strings[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
68
internal/publicip/api/api_test.go
Normal file
68
internal/publicip/api/api_test.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_ParseProvider(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := map[string]struct {
|
||||||
|
s string
|
||||||
|
provider Provider
|
||||||
|
errWrapped error
|
||||||
|
errMessage string
|
||||||
|
}{
|
||||||
|
"empty": {
|
||||||
|
errWrapped: ErrProviderNotValid,
|
||||||
|
errMessage: `API name is not valid: "" can only be ` +
|
||||||
|
`"cloudflare", "ifconfigco", "ip2location", "ipinfo" or a custom echoip# url`,
|
||||||
|
},
|
||||||
|
"invalid": {
|
||||||
|
s: "xyz",
|
||||||
|
errWrapped: ErrProviderNotValid,
|
||||||
|
errMessage: `API name is not valid: "xyz" can only be ` +
|
||||||
|
`"cloudflare", "ifconfigco", "ip2location", "ipinfo" or a custom echoip# url`,
|
||||||
|
},
|
||||||
|
"ipinfo": {
|
||||||
|
s: "ipinfo",
|
||||||
|
provider: IPInfo,
|
||||||
|
},
|
||||||
|
"IpInfo": {
|
||||||
|
s: "IpInfo",
|
||||||
|
provider: IPInfo,
|
||||||
|
},
|
||||||
|
"echoip_url_empty": {
|
||||||
|
s: "echoip#",
|
||||||
|
errWrapped: ErrCustomURLNotValid,
|
||||||
|
errMessage: `echoip# custom URL is not valid: "" ` +
|
||||||
|
`does not match regular expression: ^http(s|):\/\/.+$`,
|
||||||
|
},
|
||||||
|
"echoip_url_invalid": {
|
||||||
|
s: "echoip#postgres://localhost:3451",
|
||||||
|
errWrapped: ErrCustomURLNotValid,
|
||||||
|
errMessage: `echoip# custom URL is not valid: "postgres://localhost:3451" ` +
|
||||||
|
`does not match regular expression: ^http(s|):\/\/.+$`,
|
||||||
|
},
|
||||||
|
"echoip_url_valid": {
|
||||||
|
s: "echoip#http://localhost:3451",
|
||||||
|
provider: Provider("echoip#http://localhost:3451"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
provider, err := ParseProvider(testCase.s)
|
||||||
|
|
||||||
|
assert.Equal(t, testCase.provider, provider)
|
||||||
|
assert.ErrorIs(t, err, testCase.errWrapped)
|
||||||
|
if testCase.errWrapped != nil {
|
||||||
|
assert.EqualError(t, err, testCase.errMessage)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,39 +6,45 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ifConfigCo struct {
|
type echoip struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
url string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIfConfigCo(client *http.Client) *ifConfigCo {
|
func newEchoip(client *http.Client, url string) *echoip {
|
||||||
return &ifConfigCo{
|
return &echoip{
|
||||||
client: client,
|
client: client,
|
||||||
|
url: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ifConfigCo) String() string {
|
func (e *echoip) String() string {
|
||||||
return string(IfConfigCo)
|
s := e.url
|
||||||
|
s = strings.TrimPrefix(s, "http://")
|
||||||
|
s = strings.TrimPrefix(s, "https://")
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ifConfigCo) CanFetchAnyIP() bool {
|
func (e *echoip) CanFetchAnyIP() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ifConfigCo) Token() string {
|
func (e *echoip) Token() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchInfo obtains information on the ip address provided
|
// FetchInfo obtains information on the ip address provided
|
||||||
// using the ifconfig.co/json API. If the ip is the zero value,
|
// using the echoip API at the url given. If the ip is the zero value,
|
||||||
// the public IP address of the machine is used as the IP.
|
// the public IP address of the machine is used as the IP.
|
||||||
func (i *ifConfigCo) FetchInfo(ctx context.Context, ip netip.Addr) (
|
func (e *echoip) FetchInfo(ctx context.Context, ip netip.Addr) (
|
||||||
result models.PublicIP, err error,
|
result models.PublicIP, err error,
|
||||||
) {
|
) {
|
||||||
url := "https://ifconfig.co/json"
|
url := e.url + "/json"
|
||||||
if ip.IsValid() {
|
if ip.IsValid() {
|
||||||
url += "?ip=" + ip.String()
|
url += "?ip=" + ip.String()
|
||||||
}
|
}
|
||||||
@@ -48,7 +54,7 @@ func (i *ifConfigCo) FetchInfo(ctx context.Context, ip netip.Addr) (
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := i.client.Do(request)
|
response, err := e.client.Do(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user