Compare commits
515 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe5ec205fc | ||
|
|
576400e0d9 | ||
|
|
f08a03106f | ||
|
|
f852b7789e | ||
|
|
b0bd06bdc5 | ||
|
|
84787f0ea2 | ||
|
|
f69b3dbbe6 | ||
|
|
ec5ec6f02c | ||
|
|
5d681e635b | ||
|
|
3deb65b529 | ||
|
|
3e527fee8b | ||
|
|
b1f1f94a76 | ||
|
|
43e140e6cc | ||
|
|
7ca9d445f1 | ||
|
|
90aaf71270 | ||
|
|
4f2570865c | ||
|
|
81556ec2e1 | ||
|
|
dd5a9c6067 | ||
|
|
982c50c756 | ||
|
|
3c7dc9b9ad | ||
|
|
8f4354936c | ||
|
|
e50941277f | ||
|
|
a72647b925 | ||
|
|
e254849009 | ||
|
|
5757f0e201 | ||
|
|
75fdf7adab | ||
|
|
702eafae4c | ||
|
|
4abb8cd87f | ||
|
|
5194361f3b | ||
|
|
bc83b75634 | ||
|
|
b1ff95affa | ||
|
|
a243d48fb1 | ||
|
|
937d09f1c3 | ||
|
|
3769092888 | ||
|
|
75281dee07 | ||
|
|
26a7c5eaef | ||
|
|
1e8254fabf | ||
|
|
43b6509b43 | ||
|
|
204c5b2446 | ||
|
|
7ab3347604 | ||
|
|
2f24a79d4d | ||
|
|
819b1fe0f6 | ||
|
|
9f04b2d56c | ||
|
|
5eff5fac67 | ||
|
|
d033d08c4d | ||
|
|
25644d061e | ||
|
|
e7372f22cb | ||
|
|
4530dd4fea | ||
|
|
072528af83 | ||
|
|
2c4d577f23 | ||
|
|
edd67e3473 | ||
|
|
f389642dba | ||
|
|
b8690c7f83 | ||
|
|
06b809a492 | ||
|
|
2ceda2faaa | ||
|
|
c7fc3afc21 | ||
|
|
af57043afd | ||
|
|
4a85f3660c | ||
|
|
69713f34b2 | ||
|
|
55801597c6 | ||
|
|
ff3cc98d46 | ||
|
|
79489796ae | ||
|
|
8e495494fd | ||
|
|
1abb716bb6 | ||
|
|
3f012dd7a3 | ||
|
|
bf6bab7963 | ||
|
|
9db10f56ef | ||
|
|
3b91e351b7 | ||
|
|
657937d272 | ||
|
|
d294fbab15 | ||
|
|
cfbf5624e1 | ||
|
|
c833e9a1a8 | ||
|
|
f1b261163b | ||
|
|
4553240601 | ||
|
|
007a4536c7 | ||
|
|
31cf5d4a5a | ||
|
|
3e3bd05c79 | ||
|
|
20deaf2950 | ||
|
|
680aef62ee | ||
|
|
f5eb4887a7 | ||
|
|
dc3452c5b7 | ||
|
|
a67efd1ad1 | ||
|
|
5dcbe79fa8 | ||
|
|
574ac9a603 | ||
|
|
6871444728 | ||
|
|
f4db7e3e53 | ||
|
|
da92b6bfb9 | ||
|
|
d713782fe1 | ||
|
|
02cde5f50b | ||
|
|
c5a7a83d3a | ||
|
|
6655a1a5e6 | ||
|
|
b8cb181070 | ||
|
|
a56471fe73 | ||
|
|
8c769812ae | ||
|
|
f7a842e4ee | ||
|
|
23c0334f68 | ||
|
|
e2ee7a0408 | ||
|
|
8f862b3df7 | ||
|
|
ae1f91a997 | ||
|
|
d4fb76770f | ||
|
|
ea28c791e6 | ||
|
|
251555f859 | ||
|
|
fa7bda7ee4 | ||
|
|
f385c4203a | ||
|
|
1e4243dedb | ||
|
|
5f78ee7b79 | ||
|
|
c6eb5c1785 | ||
|
|
11338b6382 | ||
|
|
6f3a074e00 | ||
|
|
e827079604 | ||
|
|
cf66db8d4b | ||
|
|
25acbf8501 | ||
|
|
e4c7a887d2 | ||
|
|
fb8a615660 | ||
|
|
1d9d49f406 | ||
|
|
0069b59ffe | ||
|
|
d4ba1b1e09 | ||
|
|
3a20b84f3a | ||
|
|
d52fc777ac | ||
|
|
5753a428d8 | ||
|
|
85afef5775 | ||
|
|
b4fc24995c | ||
|
|
5917bb10e4 | ||
|
|
258e150ebf | ||
|
|
96f2b2b617 | ||
|
|
d556db079b | ||
|
|
a811a82329 | ||
|
|
d17a0dae1f | ||
|
|
ef40f2f91b | ||
|
|
a921f9848c | ||
|
|
95ba3261fd | ||
|
|
fe81eb65c2 | ||
|
|
8428714cf5 | ||
|
|
bedf613cff | ||
|
|
e643ce5b99 | ||
|
|
cb64302294 | ||
|
|
8d5f2fec09 | ||
|
|
60e98235ca | ||
|
|
f55fb4055f | ||
|
|
da4e410bb7 | ||
|
|
cdd1f87437 | ||
|
|
7058373916 | ||
|
|
8dd38fd182 | ||
|
|
73479bab26 | ||
|
|
f5366c33bc | ||
|
|
db886163c2 | ||
|
|
91f5338db0 | ||
|
|
82a02287ac | ||
|
|
2dc674559e | ||
|
|
38e713fea2 | ||
|
|
2cbb14c36c | ||
|
|
610e88958e | ||
|
|
bb76477467 | ||
|
|
433a799759 | ||
|
|
22965ccce3 | ||
|
|
4257581f55 | ||
|
|
d60d629105 | ||
|
|
3f721b1717 | ||
|
|
97049bfab4 | ||
|
|
84944a87d3 | ||
|
|
fb62910b17 | ||
|
|
1cc0f5fee9 | ||
|
|
6896cf4258 | ||
|
|
188d63c6b8 | ||
|
|
cbc5d466f6 | ||
|
|
aef14a9f6d | ||
|
|
f48392064e | ||
|
|
994bdd0ca7 | ||
|
|
40ed070f21 | ||
|
|
f1e4b9937b | ||
|
|
0423388b52 | ||
|
|
096a9c5fc0 | ||
|
|
7518f74729 | ||
|
|
854401a150 | ||
|
|
a7a7efe9c3 | ||
|
|
31883f9adb | ||
|
|
3b04677f8f | ||
|
|
b5fb2b849a | ||
|
|
0c9f74ffa4 | ||
|
|
58da55da1e | ||
|
|
db64dea664 | ||
|
|
f7bff247aa | ||
|
|
edc08c46d4 | ||
|
|
78d83145ba | ||
|
|
0c81154f36 | ||
|
|
53fe08ea26 | ||
|
|
a6cb1a7052 | ||
|
|
c64fe7e45d | ||
|
|
a062135148 | ||
|
|
5ae7c15211 | ||
|
|
f29707fa9f | ||
|
|
e97d1e4a9a | ||
|
|
ed4fcc17b3 | ||
|
|
716eb14da1 | ||
|
|
f92489f99b | ||
|
|
ea3b3bc8a3 | ||
|
|
a80cb8f9ba | ||
|
|
d4813ba21c | ||
|
|
bf92008e45 | ||
|
|
9c73faaaeb | ||
|
|
f9bef8ecda | ||
|
|
302adb26d7 | ||
|
|
af606463ea | ||
|
|
c932f48a95 | ||
|
|
84c1f46ae4 | ||
|
|
b27e637894 | ||
|
|
4da9607b4d | ||
|
|
8abc22977c | ||
|
|
6f4be72785 | ||
|
|
0d2ca377df | ||
|
|
98f778c3bb | ||
|
|
9b9ae69404 | ||
|
|
1c747a10c8 | ||
|
|
c4354871f7 | ||
|
|
9f6450502c | ||
|
|
ae7fc5fe96 | ||
|
|
ec157f102b | ||
|
|
fbecbc1c82 | ||
|
|
ecf76896a2 | ||
|
|
ae876b93d7 | ||
|
|
606f2cffce | ||
|
|
564d9cbf90 | ||
|
|
c5b5ae9ca7 | ||
|
|
4e0bd46dd5 | ||
|
|
f9b6e854b1 | ||
|
|
1fc1776dbf | ||
|
|
464c7074d0 | ||
|
|
cb1520cb18 | ||
|
|
e0e450ca1c | ||
|
|
1c012e4c92 | ||
|
|
78ce272bd0 | ||
|
|
a19efbd923 | ||
|
|
ee64cbf1fd | ||
|
|
5b3cbb6906 | ||
|
|
443c7e36d7 | ||
|
|
22b389b6f8 | ||
|
|
797fa33971 | ||
|
|
9dcc00900e | ||
|
|
7c102c0028 | ||
|
|
aac5274eab | ||
|
|
049bc5b226 | ||
|
|
d463e4cb69 | ||
|
|
99ba56f574 | ||
|
|
93aaf1ab02 | ||
|
|
aa9693a84d | ||
|
|
6fc2b3dd21 | ||
|
|
7e3e6f166a | ||
|
|
c614a192a4 | ||
|
|
b10a476622 | ||
|
|
15ddbdefef | ||
|
|
78323f0a33 | ||
|
|
cd60fe4406 | ||
|
|
a2a9410053 | ||
|
|
f95f6201b1 | ||
|
|
90e5742211 | ||
|
|
8f547500d0 | ||
|
|
0811b8b099 | ||
|
|
c5c53a2ff8 | ||
|
|
0ce129b63d | ||
|
|
fec1249293 | ||
|
|
a5c35455d1 | ||
|
|
28e0abc922 | ||
|
|
a13be8f45e | ||
|
|
85bd4f2e8d | ||
|
|
4baf0420d6 | ||
|
|
29f74df450 | ||
|
|
fab9939b26 | ||
|
|
b4a4e441c1 | ||
|
|
e8526141be | ||
|
|
9abb630692 | ||
|
|
9b92ece5a1 | ||
|
|
87a3e54044 | ||
|
|
76b730e2a6 | ||
|
|
51af8d1ab0 | ||
|
|
002ffacd35 | ||
|
|
404cee9371 | ||
|
|
f89e7aa8dc | ||
|
|
a0312ec916 | ||
|
|
83cf59b93e | ||
|
|
ad5de13c25 | ||
|
|
1281026850 | ||
|
|
616ba0c538 | ||
|
|
8c7c8f7d5a | ||
|
|
78877483e9 | ||
|
|
de7f12d958 | ||
|
|
7e7312459d | ||
|
|
e3a677c22b | ||
|
|
2f955e0190 | ||
|
|
618441b008 | ||
|
|
4a7d341c57 | ||
|
|
95ad58687d | ||
|
|
0fc69e068e | ||
|
|
7252ac722c | ||
|
|
4cd6b33044 | ||
|
|
0731b1cb82 | ||
|
|
07efea612b | ||
|
|
6afa4f69a0 | ||
|
|
2acf627918 | ||
|
|
4eb7c4ac36 | ||
|
|
b4c838e6ab | ||
|
|
8b096af04e | ||
|
|
78b63174ce | ||
|
|
11fca08028 | ||
|
|
515e72a0ed | ||
|
|
2f9d1f09d3 | ||
|
|
b1596bc7e4 | ||
|
|
ccf11990f1 | ||
|
|
1ac06ee4a8 | ||
|
|
dc1c7eab81 | ||
|
|
5bf471767d | ||
|
|
3d25db1bed | ||
|
|
99e386abc8 | ||
|
|
8669748289 | ||
|
|
a39d885e34 | ||
|
|
7d36993450 | ||
|
|
0d53461706 | ||
|
|
758f316816 | ||
|
|
ad73a027f3 | ||
|
|
2c96f91043 | ||
|
|
53b7fafc49 | ||
|
|
7450ffce2b | ||
|
|
765f06e5a8 | ||
|
|
e304b4a829 | ||
|
|
3ae4523280 | ||
|
|
7a136db085 | ||
|
|
e809e178b9 | ||
|
|
dd529a48fa | ||
|
|
2c6eae4e90 | ||
|
|
18e99d07d0 | ||
|
|
a4b0e0ff86 | ||
|
|
7e36fbbd00 | ||
|
|
d228216d1c | ||
|
|
c9368e352c | ||
|
|
d947d9fe30 | ||
|
|
613ded51ab | ||
|
|
3b43b7c2f6 | ||
|
|
cdbb7bf771 | ||
|
|
5a6cf0fe3a | ||
|
|
082a5bdf51 | ||
|
|
7369808b84 | ||
|
|
4f502abcf8 | ||
|
|
bdcadf09ec | ||
|
|
8cae369186 | ||
|
|
a3d75f3d8b | ||
|
|
1a06d01ae2 | ||
|
|
634cef2bb2 | ||
|
|
6107f5c4ab | ||
|
|
6ae9dc5c2c | ||
|
|
ea3a173e3b | ||
|
|
69217f61a1 | ||
|
|
e33a6a8503 | ||
|
|
0fb065eb61 | ||
|
|
f6a2aac475 | ||
|
|
900fa261d8 | ||
|
|
cfb4dd84bc | ||
|
|
4f72f60a3e | ||
|
|
f262ee6454 | ||
|
|
20a3327815 | ||
|
|
3ab1298b1f | ||
|
|
a7739b6f5d | ||
|
|
263368af89 | ||
|
|
96e57d2c32 | ||
|
|
85a93bdd34 | ||
|
|
cc80d224c2 | ||
|
|
c85cca7fdc | ||
|
|
3f6d3d7c2a | ||
|
|
09a0ba1228 | ||
|
|
6b81ed6bde | ||
|
|
64e447b262 | ||
|
|
d0926111e0 | ||
|
|
aac4298f69 | ||
|
|
f4018d3411 | ||
|
|
0710199409 | ||
|
|
43c15b3e68 | ||
|
|
ab223a5e06 | ||
|
|
fd5e7af3ff | ||
|
|
886d4ad1a9 | ||
|
|
40a72b6189 | ||
|
|
5eb1859f41 | ||
|
|
b45fa026dd | ||
|
|
da739a0c3d | ||
|
|
0dc400b540 | ||
|
|
d12668d57f | ||
|
|
c39affeb12 | ||
|
|
d73765a5f5 | ||
|
|
37282c014b | ||
|
|
adeccf8548 | ||
|
|
a97cbcc4e4 | ||
|
|
89187b6b86 | ||
|
|
754bab9763 | ||
|
|
0d7f6dab1a | ||
|
|
507374ca4e | ||
|
|
318c3c9032 | ||
|
|
c068484fa0 | ||
|
|
7cd35737ba | ||
|
|
0247a1ff01 | ||
|
|
363fabc810 | ||
|
|
6049b10209 | ||
|
|
bc05ff34fd | ||
|
|
8e77842f1e | ||
|
|
41168f88cd | ||
|
|
88ad10d429 | ||
|
|
f4cd1896c9 | ||
|
|
944e6a107b | ||
|
|
b6135d2476 | ||
|
|
c9b6e79792 | ||
|
|
94255aaa38 | ||
|
|
ac706bd156 | ||
|
|
d864a9f580 | ||
|
|
a32318d246 | ||
|
|
45a7a5b9e2 | ||
|
|
9af2a7a640 | ||
|
|
eb62ad06db | ||
|
|
a033637e85 | ||
|
|
b0ea739c20 | ||
|
|
352af84977 | ||
|
|
eb149ee040 | ||
|
|
9b3166a2e2 | ||
|
|
e94f4283e1 | ||
|
|
ef0959a15e | ||
|
|
36424c08ac | ||
|
|
97ea5f63b8 | ||
|
|
88c9d3d687 | ||
|
|
f1569dac05 | ||
|
|
4cb32ef9dc | ||
|
|
e805d42197 | ||
|
|
cbd11bfdf2 | ||
|
|
422bd8d428 | ||
|
|
58459f0336 | ||
|
|
6f6e227b94 | ||
|
|
e015cd4a27 | ||
|
|
768147095f | ||
|
|
8f6b6306d6 | ||
|
|
fb4c9b8a58 | ||
|
|
3d7cfb125a | ||
|
|
d42de99879 | ||
|
|
68203c221d | ||
|
|
3ac3e5022c | ||
|
|
da8391e9ae | ||
|
|
ebdf241888 | ||
|
|
60cec716b2 | ||
|
|
e7a475a303 | ||
|
|
67588e0072 | ||
|
|
bfa3d749ac | ||
|
|
7e79d9696f | ||
|
|
f251c6aa4d | ||
|
|
d2117cd043 | ||
|
|
0235df74a0 | ||
|
|
e5adccd9c5 | ||
|
|
76cea56864 | ||
|
|
643745d33e | ||
|
|
3d6a580102 | ||
|
|
d4a1828c1d | ||
|
|
bdf96d864e | ||
|
|
15a549be11 | ||
|
|
d534f92432 | ||
|
|
d0c61662b5 | ||
|
|
98b076e2cb | ||
|
|
0b997fe6c8 | ||
|
|
b0c0bd6364 | ||
|
|
c61a418430 | ||
|
|
e6bbaa2ba6 | ||
|
|
17ccf98c75 | ||
|
|
4db67c70b8 | ||
|
|
3250a20ffc | ||
|
|
6c12fdff2b | ||
|
|
f033204844 | ||
|
|
e334cf6c5f | ||
|
|
9435db8e1e | ||
|
|
d2b361b998 | ||
|
|
9d786bf338 | ||
|
|
3339455a97 | ||
|
|
0eb2e5a120 | ||
|
|
d0f678c315 | ||
|
|
0c48d2d5a0 | ||
|
|
47a197be48 | ||
|
|
28edae383b | ||
|
|
939b58c457 | ||
|
|
fa0272d5ad | ||
|
|
839c6f05dd | ||
|
|
9ada201b82 | ||
|
|
dd0170afb1 | ||
|
|
9239e840c4 | ||
|
|
96713b26cb | ||
|
|
3ad60349db | ||
|
|
5ee4e2fde0 | ||
|
|
ce4fd8bc68 | ||
|
|
90fc12a941 | ||
|
|
16995e1d93 | ||
|
|
9669938703 | ||
|
|
ac60cf8ab8 | ||
|
|
f5a32e690f | ||
|
|
4e622a92a5 | ||
|
|
d1412f43fd | ||
|
|
1b3a135920 | ||
|
|
53db4813fa | ||
|
|
2f09ed9069 | ||
|
|
9202d6c15f | ||
|
|
023f1c7e8e | ||
|
|
1aebe1a4c1 | ||
|
|
f45f40eee1 | ||
|
|
ab5d60754f | ||
|
|
83e8bb780a | ||
|
|
888d8bbf87 | ||
|
|
fbf04677f1 | ||
|
|
2051aa1b04 | ||
|
|
fc88ee135d | ||
|
|
a6f9a1a3d1 | ||
|
|
f181ff0005 | ||
|
|
71dcf23013 | ||
|
|
95ee3b4276 | ||
|
|
c42d13f14f | ||
|
|
ce11745f6f | ||
|
|
f6b91bd74f | ||
|
|
5c69ddc05f |
5
.devcontainer/.dockerignore
Normal file
5
.devcontainer/.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.dockerignore
|
||||||
|
devcontainer.json
|
||||||
|
docker-compose.yml
|
||||||
|
Dockerfile
|
||||||
|
README.md
|
||||||
1
.devcontainer/Dockerfile
Normal file
1
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1 @@
|
|||||||
|
FROM qmcgaw/godevcontainer
|
||||||
68
.devcontainer/README.md
Normal file
68
.devcontainer/README.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Development container
|
||||||
|
|
||||||
|
Development container that can be used with VSCode.
|
||||||
|
|
||||||
|
It works on Linux, Windows and OSX.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [VS code](https://code.visualstudio.com/download) installed
|
||||||
|
- [VS code remote containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) installed
|
||||||
|
- [Docker](https://www.docker.com/products/docker-desktop) installed and running
|
||||||
|
- If you don't use Linux or WSL 2, share your home directory `~/` and the directory of your project with Docker Desktop
|
||||||
|
- [Docker Compose](https://docs.docker.com/compose/install/) installed
|
||||||
|
- Ensure your host has the following and that they are accessible by Docker:
|
||||||
|
- `~/.ssh` directory
|
||||||
|
- `~/.gitconfig` file (can be empty)
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. Open the command palette in Visual Studio Code (CTRL+SHIFT+P).
|
||||||
|
1. Select `Remote-Containers: Open Folder in Container...` and choose the project directory.
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
### Customize the image
|
||||||
|
|
||||||
|
You can make changes to the [Dockerfile](Dockerfile) and then rebuild the image. For example, your Dockerfile could be:
|
||||||
|
|
||||||
|
```Dockerfile
|
||||||
|
FROM qmcgaw/godevcontainer
|
||||||
|
USER root
|
||||||
|
RUN apk add curl
|
||||||
|
USER vscode
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that you may need to use `USER root` to build as root, and then change back to `USER vscode`.
|
||||||
|
|
||||||
|
To rebuild the image, either:
|
||||||
|
|
||||||
|
- With VSCode through the command palette, select `Remote-Containers: Rebuild and reopen in container`
|
||||||
|
- With a terminal, go to this directory and `docker-compose build`
|
||||||
|
|
||||||
|
### Customize VS code settings
|
||||||
|
|
||||||
|
You can customize **settings** and **extensions** in the [devcontainer.json](devcontainer.json) definition file.
|
||||||
|
|
||||||
|
### Entrypoint script
|
||||||
|
|
||||||
|
You can bind mount a shell script to `/home/vscode/.welcome.sh` to replace the [current welcome script](shell/.welcome.sh).
|
||||||
|
|
||||||
|
### Publish a port
|
||||||
|
|
||||||
|
To access a port from your host to your development container, publish a port in [docker-compose.yml](docker-compose.yml).
|
||||||
|
|
||||||
|
### Run other services
|
||||||
|
|
||||||
|
1. Modify [docker-compose.yml](docker-compose.yml) to launch other services at the same time as this development container, such as a test database:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
database:
|
||||||
|
image: postgres
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
```
|
||||||
|
|
||||||
|
1. In [devcontainer.json](devcontainer.json), change the line `"runServices": ["vscode"],` to `"runServices": ["vscode", "database"],`.
|
||||||
|
1. In the VS code command palette, rebuild the container.
|
||||||
@@ -1,62 +1,81 @@
|
|||||||
{
|
{
|
||||||
"name": "pia-dev",
|
"name": "gluetun-dev",
|
||||||
"dockerComposeFile": ["docker-compose.yml"],
|
"dockerComposeFile": [
|
||||||
|
"docker-compose.yml"
|
||||||
|
],
|
||||||
"service": "vscode",
|
"service": "vscode",
|
||||||
"runServices": ["vscode"],
|
"runServices": [
|
||||||
|
"vscode"
|
||||||
|
],
|
||||||
"shutdownAction": "stopCompose",
|
"shutdownAction": "stopCompose",
|
||||||
// "postCreateCommand": "go mod download",
|
"postCreateCommand": "go mod download",
|
||||||
"workspaceFolder": "/workspace",
|
"workspaceFolder": "/workspace",
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-vscode.go",
|
"golang.go",
|
||||||
"IBM.output-colorizer",
|
"eamodio.gitlens", // IDE Git information
|
||||||
"eamodio.gitlens",
|
|
||||||
"mhutchie.git-graph",
|
|
||||||
"davidanson.vscode-markdownlint",
|
"davidanson.vscode-markdownlint",
|
||||||
"shardulm94.trailing-spaces",
|
"ms-azuretools.vscode-docker", // Docker integration and linting
|
||||||
"alefragnani.Bookmarks",
|
"shardulm94.trailing-spaces", // Show trailing spaces
|
||||||
"Gruntfuggly.todo-tree",
|
"Gruntfuggly.todo-tree", // Highlights TODO comments
|
||||||
"mohsen1.prettify-json",
|
"bierner.emojisense", // Emoji sense for markdown
|
||||||
"quicktype.quicktype",
|
"stkb.rewrap", // rewrap comments after n characters on one line
|
||||||
"spikespaz.vscode-smoothtype",
|
"vscode-icons-team.vscode-icons", // Better file extension icons
|
||||||
"stkb.rewrap",
|
"github.vscode-pull-request-github", // Github interaction
|
||||||
"vscode-icons-team.vscode-icons"
|
"redhat.vscode-yaml", // Kubernetes, Drone syntax highlighting
|
||||||
|
"bajdzis.vscode-database", // Supports connections to mysql or postgres, over SSL, socked
|
||||||
|
"IBM.output-colorizer", // Colorize your output/test logs
|
||||||
|
"mohsen1.prettify-json", // Prettify JSON data
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
// General settings
|
|
||||||
"files.eol": "\n",
|
"files.eol": "\n",
|
||||||
// Docker
|
|
||||||
"remote.extensionKind": {
|
"remote.extensionKind": {
|
||||||
"ms-azuretools.vscode-docker": "workspace"
|
"ms-azuretools.vscode-docker": "workspace"
|
||||||
},
|
},
|
||||||
// Golang general settings
|
"editor.codeActionsOnSaveTimeout": 3000,
|
||||||
"go.useLanguageServer": true,
|
"go.useLanguageServer": true,
|
||||||
|
"[go]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": true,
|
||||||
|
},
|
||||||
|
// Optional: Disable snippets, as they conflict with completion ranking.
|
||||||
|
"editor.snippetSuggestions": "none"
|
||||||
|
},
|
||||||
|
"[go.mod]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"gopls": {
|
||||||
|
"usePlaceholders": false,
|
||||||
|
"staticcheck": true
|
||||||
|
},
|
||||||
"go.autocompleteUnimportedPackages": true,
|
"go.autocompleteUnimportedPackages": true,
|
||||||
"go.gotoSymbol.includeImports": true,
|
"go.gotoSymbol.includeImports": true,
|
||||||
"go.gotoSymbol.includeGoroot": true,
|
"go.gotoSymbol.includeGoroot": true,
|
||||||
"gopls": {
|
"go.lintTool": "golangci-lint",
|
||||||
"completeUnimported": true,
|
"go.buildOnSave": "workspace",
|
||||||
"deepCompletion": true,
|
"go.lintOnSave": "workspace",
|
||||||
"usePlaceholders": false
|
"go.vetOnSave": "workspace",
|
||||||
},
|
|
||||||
// Golang on save
|
|
||||||
"go.buildOnSave": "package",
|
|
||||||
"go.lintOnSave": "package",
|
|
||||||
"go.vetOnSave": "package",
|
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"[go]": {
|
|
||||||
"editor.codeActionsOnSave": {
|
|
||||||
"source.organizeImports": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Golang testing
|
|
||||||
"go.toolsEnvVars": {
|
"go.toolsEnvVars": {
|
||||||
"GOFLAGS": "-tags=integration"
|
"GOFLAGS": "-tags=",
|
||||||
|
// "CGO_ENABLED": 1 // for the race detector
|
||||||
},
|
},
|
||||||
"gopls.env": {
|
"gopls.env": {
|
||||||
"GOFLAGS": "-tags=integration"
|
"GOFLAGS": "-tags="
|
||||||
},
|
},
|
||||||
"go.testEnvVars": {},
|
"go.testEnvVars": {
|
||||||
"go.testFlags": ["-v"],
|
"": ""
|
||||||
"go.testTimeout": "600s"
|
},
|
||||||
|
"go.testFlags": [
|
||||||
|
"-v",
|
||||||
|
// "-race"
|
||||||
|
],
|
||||||
|
"go.testTimeout": "10s",
|
||||||
|
"go.coverOnSingleTest": true,
|
||||||
|
"go.coverOnSingleTestFile": true,
|
||||||
|
"go.coverOnTestPackage": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,24 @@ version: "3.7"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
vscode:
|
vscode:
|
||||||
image: qmcgaw/godevcontainer
|
build: .
|
||||||
|
image: godevcontainer
|
||||||
volumes:
|
volumes:
|
||||||
- ../:/workspace
|
- ../:/workspace
|
||||||
- ~/.ssh:/home/vscode/.ssh:ro
|
# Docker socket to access Docker server
|
||||||
- ~/.ssh:/root/.ssh:ro
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# SSH directory
|
||||||
|
- ~/.ssh:/home/vscode/.ssh
|
||||||
|
- ~/.ssh:/root/.ssh
|
||||||
|
# Git config
|
||||||
|
- ~/.gitconfig:/home/districter/.gitconfig
|
||||||
|
- ~/.gitconfig:/root/.gitconfig
|
||||||
|
environment:
|
||||||
|
- TZ=
|
||||||
cap_add:
|
cap_add:
|
||||||
|
# For debugging with dlv
|
||||||
- SYS_PTRACE
|
- SYS_PTRACE
|
||||||
security_opt:
|
security_opt:
|
||||||
|
# For debugging with dlv
|
||||||
- seccomp:unconfined
|
- seccomp:unconfined
|
||||||
entrypoint: zsh -c "while sleep 1000; do :; done"
|
entrypoint: zsh -c "while sleep 1000; do :; done"
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
|
.devcontainer
|
||||||
.git
|
.git
|
||||||
.vscode
|
.github
|
||||||
readme
|
doc
|
||||||
.gitignore
|
|
||||||
.travis.yml
|
|
||||||
ci.sh
|
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
|
Dockerfile
|
||||||
LICENSE
|
LICENSE
|
||||||
README.md
|
README.md
|
||||||
Dockerfile
|
title.svg
|
||||||
|
|||||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@qdm12
|
||||||
18
.github/CONTRIBUTING.md
vendored
Normal file
18
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Contributions are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [open source license of this project](../LICENSE).
|
||||||
|
|
||||||
|
## Submitting a pull request
|
||||||
|
|
||||||
|
1. [Fork](https://github.com/qdm12/gluetun/fork) and clone the repository
|
||||||
|
1. Create a new branch `git checkout -b my-branch-name`
|
||||||
|
1. Modify the code
|
||||||
|
1. Ensure the docker build succeeds `docker build .` (you might need `export DOCKER_BUILDKIT=1`)
|
||||||
|
1. Commit your modifications
|
||||||
|
1. Push to your fork and [submit a pull request](https://github.com/qdm12/gluetun/compare)
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Gluetun guide on development](https://github.com/qdm12/gluetun/wiki/Development)
|
||||||
|
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
|
||||||
|
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
|
||||||
37
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
37
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: Bug
|
||||||
|
about: Report a bug
|
||||||
|
title: 'Bug: FILL THIS TEXT!'
|
||||||
|
labels: ":bug: bug"
|
||||||
|
assignees: qdm12
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Host OS** (approximate answer is fine too): Ubuntu 18
|
||||||
|
|
||||||
|
**Is this urgent?**: No
|
||||||
|
|
||||||
|
**What VPN provider are you using**:
|
||||||
|
|
||||||
|
**What are you using to run your container?**: Docker Compose
|
||||||
|
|
||||||
|
**What is the version of the program** (See the line at the top of your logs)
|
||||||
|
|
||||||
|
```
|
||||||
|
Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)
|
||||||
|
```
|
||||||
|
|
||||||
|
**What's the problem** 🤔
|
||||||
|
|
||||||
|
That feature doesn't work
|
||||||
|
|
||||||
|
**Share your logs...**
|
||||||
|
|
||||||
|
...*careful to remove i.e. token information with PIA port forwarding*
|
||||||
|
|
||||||
|
```log
|
||||||
|
|
||||||
|
PASTE YOUR LOGS
|
||||||
|
IN THERE
|
||||||
|
|
||||||
|
```
|
||||||
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest a feature to add to this project
|
||||||
|
title: 'Feature request: FILL THIS TEXT!'
|
||||||
|
labels: ":bulb: feature request"
|
||||||
|
assignees: qdm12
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**What's the feature?** 🧐
|
||||||
|
|
||||||
|
- Support this new feature because that and that
|
||||||
|
|
||||||
|
**Optional extra information** 🚀
|
||||||
|
|
||||||
|
- I tried `docker run something` and it doesn't work
|
||||||
|
- That [url](https://github.com/qdm12/gluetun) is interesting
|
||||||
53
.github/ISSUE_TEMPLATE/help.md
vendored
Normal file
53
.github/ISSUE_TEMPLATE/help.md
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
name: Help
|
||||||
|
about: Ask for help
|
||||||
|
title: 'Help: FILL THIS TEXT!'
|
||||||
|
labels: ":pray: help wanted"
|
||||||
|
assignees:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Host OS** (approximate answer is fine too): Ubuntu 18
|
||||||
|
|
||||||
|
**Is this urgent?**: No
|
||||||
|
|
||||||
|
**What VPN provider are you using**:
|
||||||
|
|
||||||
|
**What is the version of the program** (See the line at the top of your logs)
|
||||||
|
|
||||||
|
```
|
||||||
|
Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)
|
||||||
|
```
|
||||||
|
|
||||||
|
**What's the problem** 🤔
|
||||||
|
|
||||||
|
That feature doesn't work
|
||||||
|
|
||||||
|
**Share your logs...**
|
||||||
|
|
||||||
|
...*careful to remove i.e. token information with PIA port forwarding*
|
||||||
|
|
||||||
|
```log
|
||||||
|
|
||||||
|
PASTE YOUR LOGS
|
||||||
|
IN THERE
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
**What are you using to run your container?**: Docker Compose
|
||||||
|
|
||||||
|
Please also share your configuration file:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
your .yml
|
||||||
|
content
|
||||||
|
in here
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# your docker
|
||||||
|
# run command
|
||||||
|
# in here
|
||||||
|
```
|
||||||
15
.github/dependabot.yml
vendored
Normal file
15
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# Maintain dependencies for GitHub Actions
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: docker
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: gomod
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
67
.github/labels.yml
vendored
Normal file
67
.github/labels.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
- name: "Bug :bug:"
|
||||||
|
color: "b60205"
|
||||||
|
description: ""
|
||||||
|
- name: "Feature request :bulb:"
|
||||||
|
color: "0e8a16"
|
||||||
|
description: ""
|
||||||
|
- name: "Help wanted :pray:"
|
||||||
|
color: "4caf50"
|
||||||
|
description: ""
|
||||||
|
- name: "Documentation :memo:"
|
||||||
|
color: "c5def5"
|
||||||
|
description: ""
|
||||||
|
- name: "Needs more info :thinking:"
|
||||||
|
color: "795548"
|
||||||
|
description: ""
|
||||||
|
|
||||||
|
# VPN providers
|
||||||
|
- name: ":cloud: Cyberghost"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: Mullvad"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: NordVPN"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: PIA"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: Privado"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: PureVPN"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: Surfshark"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: Vyprvpn"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
- name: ":cloud: Windscribe"
|
||||||
|
color: "cfe8d4"
|
||||||
|
description: ""
|
||||||
|
|
||||||
|
# Problem category
|
||||||
|
- name: "Openvpn"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
|
- name: "Unbound (DNS over TLS)"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
|
- name: "Firewall"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
|
- name: "HTTP proxy"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
|
- name: "Shadowsocks"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
|
- name: "Healthcheck server"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
|
- name: "Control server"
|
||||||
|
color: "ffc7ea"
|
||||||
|
description: ""
|
||||||
100
.github/workflows/build.yml
vendored
Normal file
100
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- .github/workflows/build.yml
|
||||||
|
- cmd/**
|
||||||
|
- internal/**
|
||||||
|
- pkg/**
|
||||||
|
- .dockerignore
|
||||||
|
- .golangci.yml
|
||||||
|
- Dockerfile
|
||||||
|
- go.mod
|
||||||
|
- go.sum
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
verify:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
DOCKER_BUILDKIT: "1"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Linting
|
||||||
|
run: docker build --target lint .
|
||||||
|
|
||||||
|
- name: Go mod tidy check
|
||||||
|
run: docker build --target tidy .
|
||||||
|
|
||||||
|
- name: Build test image
|
||||||
|
run: docker build --target test -t test-container .
|
||||||
|
|
||||||
|
- name: Run tests in test container
|
||||||
|
run: |
|
||||||
|
touch coverage.txt
|
||||||
|
docker run --rm \
|
||||||
|
-v "$(pwd)/coverage.txt:/tmp/gobuild/coverage.txt" \
|
||||||
|
test-container \
|
||||||
|
go test \
|
||||||
|
-race \
|
||||||
|
-coverpkg=./... \
|
||||||
|
-coverprofile=coverage.txt \
|
||||||
|
-covermode=atomic \
|
||||||
|
./...
|
||||||
|
|
||||||
|
# We run this here to use the caching of the previous steps
|
||||||
|
- if: github.event_name == 'push'
|
||||||
|
name: Build final image
|
||||||
|
run: docker build .
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: [verify]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: docker/setup-qemu-action@v1
|
||||||
|
- uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: qmcgaw
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Set variables
|
||||||
|
id: vars
|
||||||
|
env:
|
||||||
|
EVENT_NAME: ${{ github.event_name }}
|
||||||
|
run: |
|
||||||
|
BRANCH=${GITHUB_REF#refs/heads/}
|
||||||
|
TAG=${GITHUB_REF#refs/tags/}
|
||||||
|
echo ::set-output name=commit::$(git rev-parse --short HEAD)
|
||||||
|
echo ::set-output name=build_date::$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||||
|
if [ "$TAG" != "$GITHUB_REF" ]; then
|
||||||
|
echo ::set-output name=version::$TAG
|
||||||
|
echo ::set-output name=platforms::linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7,linux/s390x,linux/ppc64le
|
||||||
|
elif [ "$BRANCH" = "master" ]; then
|
||||||
|
echo ::set-output name=version::latest
|
||||||
|
echo ::set-output name=platforms::linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7,linux/s390x,linux/ppc64le
|
||||||
|
else
|
||||||
|
echo ::set-output name=version::$BRANCH
|
||||||
|
echo ::set-output name=platforms::linux/amd64
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build and push final image
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
platforms: ${{ steps.vars.outputs.platforms }}
|
||||||
|
build-args: |
|
||||||
|
BUILD_DATE=${{ steps.vars.outputs.build_date }}
|
||||||
|
COMMIT=${{ steps.vars.outputs.commit }}
|
||||||
|
VERSION=${{ steps.vars.outputs.version }}
|
||||||
|
tags: |
|
||||||
|
qmcgaw/gluetun:${{ steps.vars.outputs.version }}
|
||||||
|
qmcgaw/private-internet-access:${{ steps.vars.outputs.version }}
|
||||||
|
push: true
|
||||||
|
|
||||||
|
- if: github.event_name == 'push' && github.event.ref == 'refs/heads/master'
|
||||||
|
name: Microbadger hook
|
||||||
|
run: curl -X POST https://hooks.microbadger.com/images/qmcgaw/gluetun/l-keGI7p4IhX4QuIDMFYKhsZ1L0=
|
||||||
|
continue-on-error: true
|
||||||
21
.github/workflows/dockerhub-description.yml
vendored
Normal file
21
.github/workflows/dockerhub-description.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
name: Docker Hub description
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
paths:
|
||||||
|
- README.md
|
||||||
|
- .github/workflows/dockerhub-description.yml
|
||||||
|
jobs:
|
||||||
|
dockerHubDescription:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Docker Hub Description
|
||||||
|
uses: peter-evans/dockerhub-description@v2
|
||||||
|
with:
|
||||||
|
username: qmcgaw
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
repository: qmcgaw/gluetun
|
||||||
|
short-description: Lightweight Swiss-knife VPN client to connect to several VPN providers
|
||||||
|
readme-filepath: README.md
|
||||||
15
.github/workflows/labels.yml
vendored
Normal file
15
.github/workflows/labels.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name: labels
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
paths:
|
||||||
|
- .github/labels.yml
|
||||||
|
- .github/workflows/labels.yml
|
||||||
|
jobs:
|
||||||
|
labeler:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: crazy-max/ghaction-github-labeler@v3
|
||||||
|
with:
|
||||||
|
yaml-file: .github/labels.yml
|
||||||
15
.github/workflows/misspell.yml
vendored
Normal file
15
.github/workflows/misspell.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name: Misspells
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
jobs:
|
||||||
|
misspell:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: reviewdog/action-misspell@v1
|
||||||
|
with:
|
||||||
|
locale: "US"
|
||||||
|
level: error
|
||||||
69
.golangci.yml
Normal file
69
.golangci.yml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
linters-settings:
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
- maligned
|
||||||
|
- path: internal/server/
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- asciicheck
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- errcheck
|
||||||
|
- exhaustive
|
||||||
|
- exportloopref
|
||||||
|
- gci
|
||||||
|
- gochecknoglobals
|
||||||
|
- gochecknoinits
|
||||||
|
- gocognit
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- godot
|
||||||
|
- goheader
|
||||||
|
- goimports
|
||||||
|
- golint
|
||||||
|
- gomnd
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- interfacer
|
||||||
|
- lll
|
||||||
|
- maligned
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- nestif
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- prealloc
|
||||||
|
- rowserrcheck
|
||||||
|
- scopelint
|
||||||
|
- sqlclosecheck
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
- whitespace
|
||||||
|
|
||||||
|
run:
|
||||||
|
skip-dirs:
|
||||||
|
- .devcontainer
|
||||||
|
- .github
|
||||||
|
- doc
|
||||||
20
.travis.yml
20
.travis.yml
@@ -1,20 +0,0 @@
|
|||||||
dist: xenial
|
|
||||||
sudo: required
|
|
||||||
git:
|
|
||||||
quiet: true
|
|
||||||
depth: 1
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- DOCKER_REPO=qmcgaw/private-internet-access
|
|
||||||
before_install:
|
|
||||||
- curl -fsSL https://get.docker.com | sh
|
|
||||||
- echo '{"experimental":"enabled"}' | sudo tee /etc/docker/daemon.json
|
|
||||||
- mkdir -p $HOME/.docker
|
|
||||||
- echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json
|
|
||||||
- sudo service docker start
|
|
||||||
install:
|
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
|
||||||
- docker buildx create --name xbuilder --use
|
|
||||||
script: bash ci.sh
|
|
||||||
after_success:
|
|
||||||
- curl -X POST https://hooks.microbadger.com/images/$DOCKER_REPO/tQFy7AxtSUNANPe6aoVChYdsI_I= || exit 0
|
|
||||||
8
.vscode/extensions.json
vendored
8
.vscode/extensions.json
vendored
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"shardulm94.trailing-spaces",
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"davidanson.vscode-markdownlint",
|
|
||||||
"IBM.output-colorizer"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
225
Dockerfile
225
Dockerfile
@@ -1,71 +1,154 @@
|
|||||||
ARG ALPINE_VERSION=3.11
|
ARG ALPINE_VERSION=3.12
|
||||||
ARG GO_VERSION=1.13.7
|
ARG GO_VERSION=1.15
|
||||||
|
ARG BUILDPLATFORM=linux/amd64
|
||||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder
|
|
||||||
RUN apk --update add git
|
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
|
||||||
WORKDIR /tmp/gobuild
|
RUN apk --update add git
|
||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
COPY go.mod go.sum ./
|
WORKDIR /tmp/gobuild
|
||||||
RUN go mod download 2>&1
|
COPY go.mod go.sum ./
|
||||||
COPY internal/ ./internal/
|
RUN go mod download
|
||||||
COPY cmd/main.go .
|
COPY cmd/ ./cmd/
|
||||||
RUN go test ./...
|
COPY internal/ ./internal/
|
||||||
RUN go build -ldflags="-s -w" -o entrypoint main.go
|
|
||||||
|
FROM --platform=$BUILDPLATFORM base AS test
|
||||||
FROM alpine:${ALPINE_VERSION}
|
# Note on the go race detector:
|
||||||
ARG VERSION
|
# - we set CGO_ENABLED=1 to have it enabled
|
||||||
ARG BUILD_DATE
|
# - we install g++ to support the race detector
|
||||||
ARG VCS_REF
|
ENV CGO_ENABLED=1
|
||||||
ENV VERSION=$VERSION \
|
RUN apk --update --no-cache add g++
|
||||||
BUILD_DATE=$BUILD_DATE \
|
|
||||||
VCS_REF=$VCS_REF
|
FROM --platform=$BUILDPLATFORM base AS lint
|
||||||
LABEL \
|
ARG GOLANGCI_LINT_VERSION=v1.35.2
|
||||||
org.opencontainers.image.authors="quentin.mcgaw@gmail.com" \
|
RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \
|
||||||
org.opencontainers.image.created=$BUILD_DATE \
|
sh -s -- -b /usr/local/bin ${GOLANGCI_LINT_VERSION}
|
||||||
org.opencontainers.image.version=$VERSION \
|
COPY .golangci.yml ./
|
||||||
org.opencontainers.image.revision=$VCS_REF \
|
RUN golangci-lint run --timeout=10m
|
||||||
org.opencontainers.image.url="https://github.com/qdm12/private-internet-access-docker" \
|
|
||||||
org.opencontainers.image.documentation="https://github.com/qdm12/private-internet-access-docker" \
|
FROM --platform=$BUILDPLATFORM base AS tidy
|
||||||
org.opencontainers.image.source="https://github.com/qdm12/private-internet-access-docker" \
|
RUN git init && \
|
||||||
org.opencontainers.image.title="PIA client" \
|
git config user.email ci@localhost && \
|
||||||
org.opencontainers.image.description="VPN client to tunnel to private internet access servers using OpenVPN, IPtables, DNS over TLS and Alpine Linux"
|
git config user.name ci && \
|
||||||
ENV USER= \
|
git add -A && git commit -m ci && \
|
||||||
PASSWORD= \
|
sed -i '/\/\/ indirect/d' go.mod && \
|
||||||
ENCRYPTION=strong \
|
go mod tidy && \
|
||||||
PROTOCOL=udp \
|
git diff --exit-code -- go.mod
|
||||||
REGION="CA Montreal" \
|
|
||||||
DOT=on \
|
FROM --platform=$BUILDPLATFORM base AS build
|
||||||
DOT_PROVIDERS=cloudflare \
|
COPY --from=qmcgaw/xcputranslate:v0.4.0 /xcputranslate /usr/local/bin/xcputranslate
|
||||||
DOT_PRIVATE_ADDRESS=127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1/128,fc00::/7,fe80::/10,::ffff:0:0/96 \
|
ARG TARGETPLATFORM
|
||||||
DOT_VERBOSITY=1 \
|
ARG VERSION=unknown
|
||||||
DOT_VERBOSITY_DETAILS=0 \
|
ARG BUILD_DATE="an unknown date"
|
||||||
DOT_VALIDATION_LOGLEVEL=0 \
|
ARG COMMIT=unknown
|
||||||
DOT_CACHING=on \
|
RUN GOARCH="$(xcputranslate -field arch -targetplatform ${TARGETPLATFORM})" \
|
||||||
BLOCK_MALICIOUS=on \
|
GOARM="$(xcputranslate -field arm -targetplatform ${TARGETPLATFORM})" \
|
||||||
BLOCK_SURVEILLANCE=off \
|
go build -trimpath -ldflags="-s -w \
|
||||||
BLOCK_ADS=off \
|
-X 'main.version=$VERSION' \
|
||||||
UNBLOCK= \
|
-X 'main.buildDate=$BUILD_DATE' \
|
||||||
EXTRA_SUBNETS= \
|
-X 'main.commit=$COMMIT' \
|
||||||
PORT_FORWARDING=off \
|
" -o entrypoint cmd/gluetun/main.go
|
||||||
PORT_FORWARDING_STATUS_FILE="/forwarded_port" \
|
|
||||||
TINYPROXY=off \
|
FROM alpine:${ALPINE_VERSION}
|
||||||
TINYPROXY_LOG=Info \
|
ARG VERSION=unknown
|
||||||
TINYPROXY_PORT=8888 \
|
ARG BUILD_DATE="an unknown date"
|
||||||
TINYPROXY_USER= \
|
ARG COMMIT=unknown
|
||||||
TINYPROXY_PASSWORD= \
|
LABEL \
|
||||||
SHADOWSOCKS=off \
|
org.opencontainers.image.authors="quentin.mcgaw@gmail.com" \
|
||||||
SHADOWSOCKS_LOG=on \
|
org.opencontainers.image.created=$BUILD_DATE \
|
||||||
SHADOWSOCKS_PORT=8388 \
|
org.opencontainers.image.version=$VERSION \
|
||||||
SHADOWSOCKS_PASSWORD= \
|
org.opencontainers.image.revision=$COMMIT \
|
||||||
TZ=
|
org.opencontainers.image.url="https://github.com/qdm12/gluetun" \
|
||||||
ENTRYPOINT /entrypoint
|
org.opencontainers.image.documentation="https://github.com/qdm12/gluetun" \
|
||||||
EXPOSE 8888/tcp 8388/tcp 8388/udp
|
org.opencontainers.image.source="https://github.com/qdm12/gluetun" \
|
||||||
HEALTHCHECK --interval=3m --timeout=3s --start-period=20s --retries=1 CMD /entrypoint healthcheck
|
org.opencontainers.image.title="VPN swiss-knife like client for multiple VPN providers" \
|
||||||
RUN apk add -q --progress --no-cache --update openvpn ca-certificates iptables unbound tinyproxy tzdata && \
|
org.opencontainers.image.description="VPN swiss-knife like client to tunnel to multiple VPN servers using OpenVPN, IPtables, DNS over TLS, Shadowsocks, an HTTP proxy and Alpine Linux"
|
||||||
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
ENV VPNSP=pia \
|
||||||
apk add -q --progress --no-cache --update shadowsocks-libev && \
|
VERSION_INFORMATION=on \
|
||||||
rm -rf /*.zip /var/cache/apk/* /etc/unbound/* /usr/sbin/unbound-anchor /usr/sbin/unbound-checkconf /usr/sbin/unbound-control /usr/sbin/unbound-control-setup /usr/sbin/unbound-host /etc/tinyproxy/tinyproxy.conf && \
|
PROTOCOL=udp \
|
||||||
adduser nonrootuser -D -H --uid 1000 && \
|
OPENVPN_VERBOSITY=1 \
|
||||||
chown nonrootuser -R /etc/unbound /etc/tinyproxy && \
|
OPENVPN_ROOT=yes \
|
||||||
chmod 700 /etc/unbound /etc/tinyproxy
|
OPENVPN_TARGET_IP= \
|
||||||
COPY --from=builder --chown=1000:1000 /tmp/gobuild/entrypoint /entrypoint
|
OPENVPN_IPV6=off \
|
||||||
|
TZ= \
|
||||||
|
PUID= \
|
||||||
|
PGID= \
|
||||||
|
PUBLICIP_FILE="/tmp/gluetun/ip" \
|
||||||
|
# PIA, Windscribe, Surfshark, Cyberghost, Vyprvpn, NordVPN, PureVPN only
|
||||||
|
OPENVPN_USER= \
|
||||||
|
OPENVPN_PASSWORD= \
|
||||||
|
USER_SECRETFILE=/run/secrets/openvpn_user \
|
||||||
|
PASSWORD_SECRETFILE=/run/secrets/openvpn_password \
|
||||||
|
REGION= \
|
||||||
|
# PIA only
|
||||||
|
PIA_ENCRYPTION=strong \
|
||||||
|
PORT_FORWARDING=off \
|
||||||
|
PORT_FORWARDING_STATUS_FILE="/tmp/gluetun/forwarded_port" \
|
||||||
|
# Mullvad and PureVPN only
|
||||||
|
COUNTRY= \
|
||||||
|
# Mullvad, PureVPN, Windscribe only
|
||||||
|
CITY= \
|
||||||
|
# Windscribe only
|
||||||
|
SERVER_HOSTNAME= \
|
||||||
|
# Mullvad only
|
||||||
|
ISP= \
|
||||||
|
OWNED=no \
|
||||||
|
# Mullvad and Windscribe only
|
||||||
|
PORT= \
|
||||||
|
# Cyberghost only
|
||||||
|
CYBERGHOST_GROUP="Premium UDP Europe" \
|
||||||
|
OPENVPN_CLIENTCRT_SECRETFILE=/run/secrets/openvpn_clientcrt \
|
||||||
|
OPENVPN_CLIENTKEY_SECRETFILE=/run/secrets/openvpn_clientkey \
|
||||||
|
# NordVPN only
|
||||||
|
SERVER_NUMBER= \
|
||||||
|
# Openvpn
|
||||||
|
OPENVPN_CIPHER= \
|
||||||
|
OPENVPN_AUTH= \
|
||||||
|
# DNS over TLS
|
||||||
|
DOT=on \
|
||||||
|
DOT_PROVIDERS=cloudflare \
|
||||||
|
DOT_PRIVATE_ADDRESS=127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1/128,fc00::/7,fe80::/10,::ffff:0:0/96 \
|
||||||
|
DOT_VERBOSITY=1 \
|
||||||
|
DOT_VERBOSITY_DETAILS=0 \
|
||||||
|
DOT_VALIDATION_LOGLEVEL=0 \
|
||||||
|
DOT_CACHING=on \
|
||||||
|
DOT_IPV6=off \
|
||||||
|
BLOCK_MALICIOUS=on \
|
||||||
|
BLOCK_SURVEILLANCE=off \
|
||||||
|
BLOCK_ADS=off \
|
||||||
|
UNBLOCK= \
|
||||||
|
DNS_UPDATE_PERIOD=24h \
|
||||||
|
DNS_PLAINTEXT_ADDRESS=1.1.1.1 \
|
||||||
|
DNS_KEEP_NAMESERVER=off \
|
||||||
|
# Firewall
|
||||||
|
FIREWALL=on \
|
||||||
|
FIREWALL_VPN_INPUT_PORTS= \
|
||||||
|
FIREWALL_INPUT_PORTS= \
|
||||||
|
FIREWALL_OUTBOUND_SUBNETS= \
|
||||||
|
FIREWALL_DEBUG=off \
|
||||||
|
# HTTP proxy
|
||||||
|
HTTPPROXY= \
|
||||||
|
HTTPPROXY_LOG=off \
|
||||||
|
HTTPPROXY_PORT=8888 \
|
||||||
|
HTTPPROXY_USER= \
|
||||||
|
HTTPPROXY_PASSWORD= \
|
||||||
|
HTTPPROXY_USER_SECRETFILE=/run/secrets/httpproxy_user \
|
||||||
|
HTTPPROXY_PASSWORD_SECRETFILE=/run/secrets/httpproxy_password \
|
||||||
|
# Shadowsocks
|
||||||
|
SHADOWSOCKS=off \
|
||||||
|
SHADOWSOCKS_LOG=off \
|
||||||
|
SHADOWSOCKS_PORT=8388 \
|
||||||
|
SHADOWSOCKS_PASSWORD= \
|
||||||
|
SHADOWSOCKS_PASSWORD_SECRETFILE=/run/secrets/shadowsocks_password \
|
||||||
|
SHADOWSOCKS_METHOD=chacha20-ietf-poly1305 \
|
||||||
|
UPDATER_PERIOD=0
|
||||||
|
ENTRYPOINT ["/entrypoint"]
|
||||||
|
EXPOSE 8000/tcp 8888/tcp 8388/tcp 8388/udp
|
||||||
|
HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=1 CMD /entrypoint healthcheck
|
||||||
|
RUN apk add -q --progress --no-cache --update openvpn ca-certificates iptables ip6tables unbound tzdata && \
|
||||||
|
rm -rf /var/cache/apk/* /etc/unbound/* /usr/sbin/unbound-* && \
|
||||||
|
deluser openvpn && \
|
||||||
|
deluser unbound && \
|
||||||
|
mkdir /gluetun
|
||||||
|
# TODO remove once SAN is added to PIA servers certificates, see https://github.com/pia-foss/manual-connections/issues/10
|
||||||
|
ENV GODEBUG=x509ignoreCN=0
|
||||||
|
COPY --from=build /tmp/gobuild/entrypoint /entrypoint
|
||||||
|
|||||||
392
README.md
392
README.md
@@ -1,340 +1,116 @@
|
|||||||
# Private Internet Access Client
|
# Gluetun VPN client
|
||||||
|
|
||||||
*Lightweight swiss-knife-like VPN client to tunnel to private internet access servers, using OpenVPN, iptables, DNS over TLS, ShadowSocks, Tinyproxy and more*
|
*Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access,
|
||||||
|
Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN, NordVPN, PureVPN and Privado VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
|
||||||
|
|
||||||
**ANNOUCEMENT**: *Total rewrite in Go: see the new features [below](#Features)* (in case something break use the image with tag `:old`)
|
**ANNOUNCEMENT**: *New Docker image name `qmcgaw/gluetun`*
|
||||||
|
|
||||||
<a href="https://hub.docker.com/r/qmcgaw/private-internet-access">
|
<img height="250" src="https://raw.githubusercontent.com/qdm12/gluetun/master/title.svg?sanitize=true">
|
||||||
<img width="100%" height="320" src="https://raw.githubusercontent.com/qdm12/private-internet-access-docker/master/title.svg?sanitize=true">
|
|
||||||
</a>
|
[](https://hub.docker.com/r/qmcgaw/gluetun/tags?page=1&ordering=last_updated)
|
||||||
|
[](https://hub.docker.com/r/qmcgaw/gluetun/tags)
|
||||||
|
|
||||||
[](https://travis-ci.org/qdm12/private-internet-access-docker)
|
|
||||||
[](https://hub.docker.com/r/qmcgaw/private-internet-access)
|
[](https://hub.docker.com/r/qmcgaw/private-internet-access)
|
||||||
[](https://hub.docker.com/r/qmcgaw/private-internet-access)
|
[](https://hub.docker.com/r/qmcgaw/gluetun)
|
||||||
|
|
||||||
[](https://github.com/qdm12/private-internet-access-docker/issues)
|

|
||||||
[](https://github.com/qdm12/private-internet-access-docker/issues)
|

|
||||||
[](https://github.com/qdm12/private-internet-access-docker/issues)
|

|
||||||
|
|
||||||
[](https://microbadger.com/images/qmcgaw/private-internet-access)
|

|
||||||
[](https://microbadger.com/images/qmcgaw/private-internet-access)
|
[](https://github.com/qdm12/gluetun/commits)
|
||||||
[](https://join.slack.com/t/qdm12/shared_invite/enQtOTE0NjcxNTM1ODc5LTYyZmVlOTM3MGI4ZWU0YmJkMjUxNmQ4ODQ2OTAwYzMxMTlhY2Q1MWQyOWUyNjc2ODliNjFjMDUxNWNmNzk5MDk)
|
|
||||||
|
|
||||||
<details><summary>Click to show base components</summary><p>
|
[](https://github.com/qdm12/gluetun)
|
||||||
|
|
||||||
- [Alpine 3.11](https://alpinelinux.org) for a tiny image (37MB of packages, 6.7MB of Go binary and 5.6MB for Alpine)
|
## Quick links
|
||||||
- [OpenVPN 2.4.8](https://pkgs.alpinelinux.org/package/v3.11/main/x86_64/openvpn) to tunnel to PIA servers
|
|
||||||
- [IPtables 1.8.3](https://pkgs.alpinelinux.org/package/v3.11/main/x86_64/iptables) enforces the container to communicate only through the VPN or with other containers in its virtual network (acts as a killswitch)
|
|
||||||
- [Unbound 1.9.6](https://pkgs.alpinelinux.org/package/v3.11/main/x86_64/unbound) configured with Cloudflare's [1.1.1.1](https://1.1.1.1) DNS over TLS (configurable with 5 different providers)
|
|
||||||
- [Files and blocking lists built periodically](https://github.com/qdm12/updated/tree/master/files) used with Unbound (see `BLOCK_MALICIOUS`, `BLOCK_SURVEILLANCE` and `BLOCK_ADS` environment variables)
|
|
||||||
- [TinyProxy 1.10.0](https://pkgs.alpinelinux.org/package/v3.11/main/x86_64/tinyproxy)
|
|
||||||
- [Shadowsocks 3.3.4](https://pkgs.alpinelinux.org/package/edge/testing/x86/shadowsocks-libev)
|
|
||||||
|
|
||||||
</p></details>
|
- Problem or suggestion?
|
||||||
|
- [Start a discussion](https://github.com/qdm12/gluetun/discussions)
|
||||||
|
- [Create an issue](https://github.com/qdm12/gluetun/issues)
|
||||||
|
- [Check the Wiki](https://github.com/qdm12/gluetun/wiki)
|
||||||
|
- [Join the Slack channel](https://join.slack.com/t/qdm12/shared_invite/enQtOTE0NjcxNTM1ODc5LTYyZmVlOTM3MGI4ZWU0YmJkMjUxNmQ4ODQ2OTAwYzMxMTlhY2Q1MWQyOWUyNjc2ODliNjFjMDUxNWNmNzk5MDk)
|
||||||
|
- Happy?
|
||||||
|
- Sponsor me on [github.com/sponsors/qdm12](https://github.com/sponsors/qdm12)
|
||||||
|
- Donate to [paypal.me/qmcgaw](https://www.paypal.me/qmcgaw)
|
||||||
|
- Drop me [an email](mailto:quentin.mcgaw@gmail.com)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **New features**
|
- Based on Alpine 3.12 for a small Docker image of 52MB
|
||||||
- Choice to block ads, malicious and surveillance at the DNS level
|
- Supports **Private Internet Access**, **Mullvad**, **Windscribe**, **Surfshark**, **Cyberghost**, **Vyprvpn**, **NordVPN**, **PureVPN** and **Privado** servers
|
||||||
- All program output streams are merged (openvpn, unbound, shadowsocks, tinyproxy, etc.)
|
- Supports Openvpn only for now
|
||||||
- Choice of DNS over TLS provider(s)
|
- DNS over TLS baked in with service provider(s) of your choice
|
||||||
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers
|
- DNS fine blocking of malicious/ads/surveillance hostnames and IP addresses, with live update every 24 hours
|
||||||
- Download block lists and cryptographic files at start instead of at build time
|
- Choose the vpn network protocol, `udp` or `tcp`
|
||||||
- Can work as a Kubernetes sidecar container, thanks @rorph
|
- Built in firewall kill switch to allow traffic only with needed the VPN servers and LAN devices
|
||||||
- Pick a random region if no region is given, thanks @rorph
|
- Built in Shadowsocks proxy (protocol based on SOCKS5 with an encryption layer, tunnels TCP+UDP)
|
||||||
- <details><summary>Configure everything with environment variables</summary><p>
|
- Built in HTTP proxy (tunnels HTTP and HTTPS through TCP)
|
||||||
|
- [Connect other containers to it](https://github.com/qdm12/gluetun/wiki/Connect-to-gluetun)
|
||||||
- [Destination region](https://www.privateinternetaccess.com/pages/network)
|
- [Connect LAN devices to it](https://github.com/qdm12/gluetun/wiki/Connect-to-gluetun)
|
||||||
- Internet protocol
|
- Compatible with amd64, i686 (32 bit), **ARM** 64 bit, ARM 32 bit v6 and v7, and even s390x as well as ppc64le 🎆
|
||||||
- Level of encryption
|
- VPN server side port forwarding for Private Internet Access and Vyprvpn
|
||||||
- PIA Username and password
|
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers
|
||||||
- DNS over TLS
|
- Subprograms all drop root privileges once launched
|
||||||
- DNS blocking: ads, malicious, surveillance
|
- Subprograms output streams are all merged together
|
||||||
- Internal firewall
|
- Can work as a Kubernetes sidecar container, thanks @rorph
|
||||||
- Socks5 proxy
|
|
||||||
- Web HTTP proxy
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- Connect
|
|
||||||
- [Other containers to it](https://github.com/qdm12/private-internet-access-docker#connect-to-it)
|
|
||||||
- [LAN devices to it](https://github.com/qdm12/private-internet-access-docker#connect-to-it)
|
|
||||||
- Killswitch using *iptables* to allow traffic only with needed PIA servers and LAN devices
|
|
||||||
- Port forwarding
|
|
||||||
- Compatible with amd64, i686 (32 bit), **ARM** 64 bit, ARM 32 bit v6 and v7, ppc64le and even that s390x 🎆
|
|
||||||
- Sub programs drop root privileges once launched: Openvpn, Unbound, Shadowsocks, Tinyproxy
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. <details><summary>Requirements</summary><p>
|
1. On some devices you may need to setup your tunnel kernel module on your host with `insmod /lib/modules/tun.ko` or `modprobe tun`
|
||||||
|
- [Synology users Wiki page](https://github.com/qdm12/gluetun/wiki/Synology-setup)
|
||||||
- A Private Internet Access **username** and **password** - [Sign up](https://www.privateinternetaccess.com/pages/buy-vpn/)
|
|
||||||
- Docker API 1.25 to support `init`
|
|
||||||
- If you use Docker Compose, docker-compose >= 1.22.0, to support `init: true`
|
|
||||||
- <details><summary>External firewall requirements, if you have one</summary><p>
|
|
||||||
|
|
||||||
- At start only
|
|
||||||
- Allow outbound TCP 443 to github.com and privateinternetaccess.com
|
|
||||||
- If `DOT=on`, allow outbound TCP 853 to 1.1.1.1 to allow Unbound to resolve the PIA domain name.
|
|
||||||
- If `DOT=off`, allow outbound UDP 53 to your DNS provider to resolve the PIA domain name.
|
|
||||||
- For UDP strong encryption, allow outbound UDP 1197 to the corresponding VPN server IPs
|
|
||||||
- For UDP normal encryption, allow outbound UDP 1198 to the corresponding VPN server IPs
|
|
||||||
- For TCP strong encryption, allow outbound TCP 501 to the corresponding VPN server IPs
|
|
||||||
- For TCP normal encryption, allow outbound TCP 502 to the corresponding VPN server IPs
|
|
||||||
- If `SHADOWSOCKS=on`, allow inbound TCP 8388 and UDP 8388 from your LAN
|
|
||||||
- If `TINYPROXY=on`, allow inbound TCP 8888 from your LAN
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
|
|
||||||
1. Launch the container with:
|
1. Launch the container with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d --init --name=pia --cap-add=NET_ADMIN \
|
docker run -d --name gluetun --cap-add=NET_ADMIN \
|
||||||
-e REGION="CA Montreal" -e USER=js89ds7 -e PASSWORD=8fd9s239G \
|
-e VPNSP="private internet access" -e REGION="CA Montreal" \
|
||||||
qmcgaw/private-internet-access
|
-e OPENVPN_USER=js89ds7 -e OPENVPN_PASSWORD=8fd9s239G \
|
||||||
|
-v /yourpath:/gluetun \
|
||||||
|
qmcgaw/gluetun
|
||||||
```
|
```
|
||||||
|
|
||||||
or use [docker-compose.yml](https://github.com/qdm12/private-internet-access-docker/blob/master/docker-compose.yml) with:
|
or use [docker-compose.yml](https://github.com/qdm12/gluetun/blob/master/docker-compose.yml) with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
echo "your openvpn username" > openvpn_user
|
||||||
|
echo "your openvpn password" > openvpn_password
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that you can:
|
You should probably check the many [environment variables](https://github.com/qdm12/gluetun/wiki/Environment-variables) available to adapt the container to your needs.
|
||||||
- Change the many [environment variables](#environment-variables) available
|
|
||||||
- Use `-p 8888:8888/tcp` to access the HTTP web proxy (and put your LAN in `EXTRA_SUBNETS` environment variable)
|
|
||||||
- Use `-p 8388:8388/tcp -p 8388:8388/udp` to access the SOCKS5 proxy (and put your LAN in `EXTRA_SUBNETS` environment variable)
|
|
||||||
- Pass additional arguments to *openvpn* using Docker's command function (commands after the image name)
|
|
||||||
1. You can update the image with `docker pull qmcgaw/private-internet-access:latest`. There are also docker tags available:
|
|
||||||
- `qmcgaw/private-internet-access:v1` linked to the [v1 release](https://github.com/qdm12/private-internet-access-docker/releases/tag/v1.0)
|
|
||||||
|
|
||||||
## Testing
|
## Further setup
|
||||||
|
|
||||||
Check the PIA IP address matches your expectations
|
The following points are all optional but should give you insights on all the possibilities with this container.
|
||||||
|
|
||||||
```sh
|
- Use [Docker secrets](https://github.com/qdm12/gluetun/wiki/Docker-secrets) to read your credentials instead of environment variables
|
||||||
docker run --rm --network=container:pia alpine:3.10 wget -qO- https://ipinfo.io
|
- [Test your setup](https://github.com/qdm12/gluetun/wiki/Test-your-setup)
|
||||||
```
|
- [How to connect other containers and devices to Gluetun](https://github.com/qdm12/gluetun/wiki/Connect-to-gluetun)
|
||||||
|
- [VPN server side port forwarding](https://github.com/qdm12/gluetun/wiki/Port-forwarding)
|
||||||
## Environment variables
|
- [HTTP control server](https://github.com/qdm12/gluetun/wiki/HTTP-Control-server) to automate things, restart Openvpn etc.
|
||||||
|
- Update the image with `docker pull qmcgaw/gluetun:latest`. See this [Wiki document](https://github.com/qdm12/gluetun/wiki/Docker-image-tags) for Docker tags available.
|
||||||
| Environment variable | Default | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `REGION` | `CA Montreal` | One of the [PIA regions](https://www.privateinternetaccess.com/pages/network/) |
|
|
||||||
| `PROTOCOL` | `udp` | `tcp` or `udp` |
|
|
||||||
| `ENCRYPTION` | `strong` | `normal` or `strong` |
|
|
||||||
| `USER` | | Your PIA username |
|
|
||||||
| `PASSWORD` | | Your PIA password |
|
|
||||||
| `DOT` | `on` | `on` or `off`, to activate DNS over TLS to 1.1.1.1 |
|
|
||||||
| `DOT_PROVIDERS` | `cloudflare` | Comma delimited list of DNS over TLS providers from `cloudflare`, `google`, `quad9`, `quadrant`, `cleanbrowsing`, `securedns`, `libredns` |
|
|
||||||
| `DOT_CACHING` | `on` | Unbound caching feature, `on` or `off` |
|
|
||||||
| `DOT_PRIVATE_ADDRESS` | All IPv4 and IPv6 CIDRs private ranges | Comma separated list of CIDRs or single IP addresses. Note that the default setting prevents DNS rebinding |
|
|
||||||
| `DOT_VERBOSITY` | `1` | Unbound verbosity level from `0` to `5` (full debug) |
|
|
||||||
| `DOT_VERBOSITY_DETAILS` | `0` | Unbound details verbosity level from `0` to `4` |
|
|
||||||
| `DOT_VALIDATION_LOGLEVEL` | `0` | Unbound validation log level from `0` to `2` |
|
|
||||||
| `BLOCK_MALICIOUS` | `on` | `on` or `off`, blocks malicious hostnames and IPs |
|
|
||||||
| `BLOCK_SURVEILLANCE` | `off` | `on` or `off`, blocks surveillance hostnames and IPs |
|
|
||||||
| `BLOCK_ADS` | `off` | `on` or `off`, blocks ads hostnames and IPs |
|
|
||||||
| `UNBLOCK` | | comma separated string (i.e. `web.com,web2.ca`) to unblock hostnames |
|
|
||||||
| `EXTRA_SUBNETS` | | comma separated subnets allowed in the container firewall (i.e. `192.168.1.0/24,192.168.10.121,10.0.0.5/28`) |
|
|
||||||
| `PORT_FORWARDING` | `off` | Set to `on` to forward a port on PIA server |
|
|
||||||
| `PORT_FORWARDING_STATUS_FILE` | `/forwarded_port` | File path to store the forwarded port number |
|
|
||||||
| `TINYPROXY` | `off` | `on` or `off`, to enable the internal HTTP proxy tinyproxy |
|
|
||||||
| `TINYPROXY_LOG` | `Info` | `Info`, `Connect`, `Notice`, `Warning`, `Error` or `Critical` |
|
|
||||||
| `TINYPROXY_PORT` | `8888` | `1024` to `65535` internal port for HTTP proxy |
|
|
||||||
| `TINYPROXY_USER` | | Username to use to connect to the HTTP proxy |
|
|
||||||
| `TINYPROXY_PASSWORD` | | Passsword to use to connect to the HTTP proxy |
|
|
||||||
| `SHADOWSOCKS` | `off` | `on` or `off`, to enable the internal SOCKS5 proxy Shadowsocks |
|
|
||||||
| `SHADOWSOCKS_LOG` | `on` | `on` or `off` to enable logging for Shadowsocks |
|
|
||||||
| `SHADOWSOCKS_PORT` | `8388` | `1024` to `65535` internal port for SOCKS5 proxy |
|
|
||||||
| `SHADOWSOCKS_PASSWORD` | | Passsword to use to connect to the SOCKS5 proxy |
|
|
||||||
| `TZ` | | Specify a timezone to use i.e. `Europe/London` |
|
|
||||||
|
|
||||||
## Connect to it
|
|
||||||
|
|
||||||
There are various ways to achieve this, depending on your use case.
|
|
||||||
|
|
||||||
- <details><summary>Connect containers in the same docker-compose.yml as PIA</summary><p>
|
|
||||||
|
|
||||||
Add `network_mode: "service:pia"` to your *docker-compose.yml* (no need for `depends_on`)
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- <details><summary>Connect other containers to PIA</summary><p>
|
|
||||||
|
|
||||||
Add `--network=container:pia` when launching the container, provided PIA is already running
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- <details><summary>Connect containers from another docker-compose.yml</summary><p>
|
|
||||||
|
|
||||||
Add `network_mode: "container:pia"` to your *docker-compose.yml*, provided PIA is already running
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- <details><summary>Connect LAN devices through the built-in HTTP proxy *Tinyproxy* (i.e. with Chrome, Kodi, etc.)</summary><p>
|
|
||||||
|
|
||||||
You might want to use Shadowsocks instead which tunnels UDP as well as TCP, whereas Tinyproxy only tunnels TCP.
|
|
||||||
|
|
||||||
1. Setup a HTTP proxy client, such as [SwitchyOmega for Chrome](https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif?hl=en)
|
|
||||||
1. Ensure the PIA container is launched with:
|
|
||||||
- port `8888` published `-p 8888:8888/tcp`
|
|
||||||
- your LAN subnet, i.e. `192.168.1.0/24`, set as `-e EXTRA_SUBNETS=192.168.1.0/24`
|
|
||||||
1. With your HTTP proxy client, connect to the Docker host (i.e. `192.168.1.10`) on port `8888`. You need to enter your credentials if you set them with `TINYPROXY_USER` and `TINYPROXY_PASSWORD`.
|
|
||||||
1. If you set `TINYPROXY_LOG` to `Info`, more information will be logged in the Docker logs
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- <details><summary>Connect LAN devices through the built-in SOCKS5 proxy *Shadowsocks* (per app, system wide, etc.)</summary><p>
|
|
||||||
|
|
||||||
1. Setup a SOCKS5 proxy client, there is a list of [ShadowSocks clients for **all platforms**](https://shadowsocks.org/en/download/clients.html)
|
|
||||||
- **note** some clients do not tunnel UDP so your DNS queries will be done locally and not through PIA and its built in DNS over TLS
|
|
||||||
- Clients that support such UDP tunneling are, as far as I know:
|
|
||||||
- iOS: Potatso Lite
|
|
||||||
- OSX: ShadowsocksX
|
|
||||||
- Android: Shadowsocks by Max Lv
|
|
||||||
1. Ensure the PIA container is launched with:
|
|
||||||
- port `8388` published `-p 8388:8388/tcp -p 8388:8388/udp`
|
|
||||||
- your LAN subnet, i.e. `192.168.1.0/24`, set as `-e EXTRA_SUBNETS=192.168.1.0/24`
|
|
||||||
1. With your SOCKS5 proxy client
|
|
||||||
- Enter the Docker host (i.e. `192.168.1.10`) as the server IP
|
|
||||||
- Enter port TCP (and UDP, if available) `8388` as the server port
|
|
||||||
- Use the password you have set with `SHADOWSOCKS_PASSWORD`
|
|
||||||
- Choose the encryption method/algorithm `chacha20-ietf-poly1305`
|
|
||||||
1. If you set `SHADOWSOCKS_LOG` to `on`, more information will be logged in the Docker logs
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- <details><summary>Access ports of containers connected to PIA</summary><p>
|
|
||||||
|
|
||||||
In example, to access port `8000` of container `xyz` and `9000` of container `abc` connected to PIA,
|
|
||||||
publish ports `8000` and `9000` for the PIA container and access them as you would with any other container
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
- <details><summary>Access ports of containers connected to PIA, all in the same docker-compose.yml</summary><p>
|
|
||||||
|
|
||||||
In example, to access port `8000` of container `xyz` and `9000` of container `abc` connected to PIA, publish port `8000` and `9000` for the PIA container.
|
|
||||||
The docker-compose.yml file would look like:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
version: '3.7'
|
|
||||||
services:
|
|
||||||
pia:
|
|
||||||
image: qmcgaw/private-internet-access
|
|
||||||
container_name: pia
|
|
||||||
init: true
|
|
||||||
cap_add:
|
|
||||||
- NET_ADMIN
|
|
||||||
environment:
|
|
||||||
- USER=js89ds7
|
|
||||||
- PASSWORD=8fd9s239G
|
|
||||||
ports:
|
|
||||||
- 8000:8000/tcp
|
|
||||||
- 9000:9000/tcp
|
|
||||||
abc:
|
|
||||||
image: abc
|
|
||||||
container_name: abc
|
|
||||||
network_mode: "service:pia"
|
|
||||||
xyz:
|
|
||||||
image: xyz
|
|
||||||
container_name: xyz
|
|
||||||
network_mode: "service:pia"
|
|
||||||
```
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
|
|
||||||
## Port forwarding
|
|
||||||
|
|
||||||
By setting `PORT_FORWARDING` environment variable to `on`, the forwarded port will be read and written to the file specified in `PORT_FORWARDING_STATUS_FILE` (by default, this is set to `/forwarded_port`). If the location for this file does not exist, it will be created automatically.
|
|
||||||
|
|
||||||
You can mount this file as a volume to read it from other containers.
|
|
||||||
|
|
||||||
Note that not all regions support port forwarding.
|
|
||||||
|
|
||||||
## For the paranoids
|
|
||||||
|
|
||||||
- You can review the code which consists in:
|
|
||||||
- [Dockerfile](https://github.com/qdm12/private-internet-access-docker/blob/master/Dockerfile)
|
|
||||||
- [main.go](https://github.com/qdm12/private-internet-access-docker/blob/master/cmd/main.go), the main code entrypoint
|
|
||||||
- [internal package](https://github.com/qdm12/private-internet-access-docker/blob/master/internal)
|
|
||||||
- [github.com/qdm12/golibs](https://github.com/qdm12/golibs) dependency
|
|
||||||
- [github.com/qdm12/files](https://github.com/qdm12/files) for files downloaded at start (DNS root hints, block lists, etc.)
|
|
||||||
- Build the image yourself:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build -t qmcgaw/private-internet-access https://github.com/qdm12/private-internet-access-docker.git
|
|
||||||
```
|
|
||||||
|
|
||||||
- The download and parsing of all needed files is done at start (openvpn config files, Unbound files, block lists, etc.)
|
|
||||||
- Use `-e ENCRYPTION=strong -e BLOCK_MALICIOUS=on`
|
|
||||||
- You can test DNSSEC using [internet.nl/connection](https://www.internet.nl/connection/)
|
|
||||||
- Check DNS leak tests with [https://www.dnsleaktest.com](https://www.dnsleaktest.com)
|
|
||||||
- DNS Leaks tests might not work because of [this](https://github.com/qdm12/cloudflare-dns-server#verify-dns-connection) (*TLDR*: DNS server is a local caching intermediary)
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
- If openvpn fails to start, you may need to:
|
|
||||||
- Install the tun kernel module on your host with `insmod /lib/modules/tun.ko` or `modprobe tun`
|
|
||||||
- Add `--device=/dev/net/tun` to your docker run command (equivalent for docker-compose, kubernetes, etc.)
|
|
||||||
|
|
||||||
- Fallback to a previous Docker image tags:
|
|
||||||
- `v1` tag, stable shell scripting based (no support)
|
|
||||||
- `old` tag, latest shell scripting version (no support)
|
|
||||||
- `v2`... waiting for `latest` to become more stable
|
|
||||||
|
|
||||||
- Fallback to a precise previous version
|
|
||||||
1. Clone the repository on your machine
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/qdm12/private-internet-access-docker.git pia
|
|
||||||
cd pia
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Look up which commit you want to go back to [here](https://github.com/qdm12/private-internet-access-docker/commits/master), i.e. `942cc7d4d10545b6f5f89c907b7dd1dbc39368e0`
|
|
||||||
1. Revert to this commit locally
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git reset --hard 942cc7d4d10545b6f5f89c907b7dd1dbc39368e0
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Build the Docker image
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker build -t qmcgaw/private-internet-access .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
### Using VSCode and Docker
|
|
||||||
|
|
||||||
1. Install [Docker](https://docs.docker.com/install)
|
|
||||||
- On Windows, share a drive with Docker Desktop and have the project on that partition
|
|
||||||
1. With [Visual Studio Code](https://code.visualstudio.com/download), install the [remote containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
|
||||||
1. In Visual Studio Code, press on `F1` and select `Remote-Containers: Open Folder in Container...`
|
|
||||||
1. Your dev environment is ready to go!... and it's running in a container :+1:
|
|
||||||
|
|
||||||
## TODOs
|
|
||||||
|
|
||||||
- Support other VPN providers
|
|
||||||
- Mullvad
|
|
||||||
- Windscribe
|
|
||||||
- Gotify support for notificactions
|
|
||||||
- Periodic update of malicious block lists with Unbound restart
|
|
||||||
- Improve healthcheck
|
|
||||||
- Check IP address belongs to selected region
|
|
||||||
- Check for DNS provider somehow if this is even possible
|
|
||||||
- Support for other VPN protocols
|
|
||||||
- Wireguard (wireguard-go)
|
|
||||||
- Show new versions/commits at start
|
|
||||||
- Colors & emojis
|
|
||||||
- Setup
|
|
||||||
- Logging streams
|
|
||||||
- More unit tests
|
|
||||||
- Write in Go
|
|
||||||
- DNS over TLS to replace Unbound
|
|
||||||
- HTTP proxy to replace tinyproxy
|
|
||||||
- use [go-Shadowsocks2](https://github.com/shadowsocks/go-shadowsocks2)
|
|
||||||
- DNS over HTTPS, maybe use [github.com/likexian/doh-go](https://github.com/likexian/doh-go)
|
|
||||||
- use [iptables-go](https://github.com/coreos/go-iptables) to replace iptables
|
|
||||||
- wireguard-go
|
|
||||||
- Openvpn to replace openvpn
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This repository is under an [MIT license](https://github.com/qdm12/private-internet-access-docker/master/license)
|
[](https://github.com/qdm12/gluetun/master/LICENSE)
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
[](https://github.com/qdm12/gluetun/commits)
|
||||||
|
[](https://github.com/qdm12/gluetun/pulls?q=is%3Apr+is%3Aclosed)
|
||||||
|
|
||||||
|
[](https://github.com/qdm12/gluetun/issues)
|
||||||
|
[](https://github.com/qdm12/gluetun/issues?q=is%3Aissue+is%3Aclosed)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
[](https://hub.docker.com/r/qmcgaw/gluetun)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|||||||
21
ci.sh
21
ci.sh
@@ -1,21 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ "$TRAVIS_PULL_REQUEST" = "true" ] || [ "$TRAVIS_BRANCH" != "master" ]; then
|
|
||||||
docker buildx build \
|
|
||||||
--progress plain \
|
|
||||||
--platform=linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6,linux/ppc64le,linux/s390x \
|
|
||||||
.
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
echo $DOCKER_PASSWORD | docker login -u qmcgaw --password-stdin &> /dev/null
|
|
||||||
TAG="${TRAVIS_TAG:-latest}"
|
|
||||||
echo "Building Docker images for \"$DOCKER_REPO:$TAG\""
|
|
||||||
docker buildx build \
|
|
||||||
--progress plain \
|
|
||||||
--platform=linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6,linux/ppc64le,linux/s390x \
|
|
||||||
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
|
|
||||||
--build-arg VCS_REF=`git rev-parse --short HEAD` \
|
|
||||||
--build-arg VERSION=$TAG \
|
|
||||||
-t $DOCKER_REPO:$TAG \
|
|
||||||
--push \
|
|
||||||
.
|
|
||||||
408
cmd/gluetun/main.go
Normal file
408
cmd/gluetun/main.go
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
nativeos "os"
|
||||||
|
"os/signal"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/dns/pkg/unbound"
|
||||||
|
"github.com/qdm12/gluetun/internal/alpine"
|
||||||
|
"github.com/qdm12/gluetun/internal/cli"
|
||||||
|
"github.com/qdm12/gluetun/internal/configuration"
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/dns"
|
||||||
|
"github.com/qdm12/gluetun/internal/firewall"
|
||||||
|
"github.com/qdm12/gluetun/internal/healthcheck"
|
||||||
|
"github.com/qdm12/gluetun/internal/httpproxy"
|
||||||
|
gluetunLogging "github.com/qdm12/gluetun/internal/logging"
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
"github.com/qdm12/gluetun/internal/openvpn"
|
||||||
|
"github.com/qdm12/gluetun/internal/publicip"
|
||||||
|
"github.com/qdm12/gluetun/internal/routing"
|
||||||
|
"github.com/qdm12/gluetun/internal/server"
|
||||||
|
"github.com/qdm12/gluetun/internal/shadowsocks"
|
||||||
|
"github.com/qdm12/gluetun/internal/storage"
|
||||||
|
"github.com/qdm12/gluetun/internal/unix"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater"
|
||||||
|
versionpkg "github.com/qdm12/gluetun/internal/version"
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
"github.com/qdm12/golibs/os/user"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
"github.com/qdm12/updated/pkg/dnscrypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:gochecknoglobals
|
||||||
|
var (
|
||||||
|
version = "unknown"
|
||||||
|
commit = "unknown"
|
||||||
|
buildDate = "an unknown date"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
buildInfo := models.BuildInformation{
|
||||||
|
Version: version,
|
||||||
|
Commit: commit,
|
||||||
|
BuildDate: buildDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
nativeos.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := nativeos.Args
|
||||||
|
os := os.New()
|
||||||
|
osUser := user.New()
|
||||||
|
unix := unix.New()
|
||||||
|
cli := cli.New()
|
||||||
|
|
||||||
|
errorCh := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errorCh <- _main(ctx, buildInfo, args, logger, os, osUser, unix, cli)
|
||||||
|
}()
|
||||||
|
|
||||||
|
signalsCh := make(chan nativeos.Signal, 1)
|
||||||
|
signal.Notify(signalsCh,
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
nativeos.Interrupt,
|
||||||
|
)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case signal := <-signalsCh:
|
||||||
|
logger.Warn("Caught OS signal %s, shutting down", signal)
|
||||||
|
case err := <-errorCh:
|
||||||
|
close(errorCh)
|
||||||
|
if err == nil { // expected exit such as healthcheck
|
||||||
|
nativeos.Exit(0)
|
||||||
|
}
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
const shutdownGracePeriod = 5 * time.Second
|
||||||
|
timer := time.NewTimer(shutdownGracePeriod)
|
||||||
|
select {
|
||||||
|
case <-errorCh:
|
||||||
|
if !timer.Stop() {
|
||||||
|
<-timer.C
|
||||||
|
}
|
||||||
|
logger.Info("Shutdown successful")
|
||||||
|
case <-timer.C:
|
||||||
|
logger.Warn("Shutdown timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeos.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gocognit,gocyclo
|
||||||
|
func _main(ctx context.Context, buildInfo models.BuildInformation,
|
||||||
|
args []string, logger logging.Logger, os os.OS, osUser user.OSUser, unix unix.Unix,
|
||||||
|
cli cli.CLI) error {
|
||||||
|
if len(args) > 1 { // cli operation
|
||||||
|
switch args[1] {
|
||||||
|
case "healthcheck":
|
||||||
|
return cli.HealthCheck(ctx)
|
||||||
|
case "clientkey":
|
||||||
|
return cli.ClientKey(args[2:], os.OpenFile)
|
||||||
|
case "openvpnconfig":
|
||||||
|
return cli.OpenvpnConfig(os)
|
||||||
|
case "update":
|
||||||
|
return cli.Update(ctx, args[2:], os)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("command %q is unknown", args[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
const clientTimeout = 15 * time.Second
|
||||||
|
httpClient := &http.Client{Timeout: clientTimeout}
|
||||||
|
// Create configurators
|
||||||
|
alpineConf := alpine.NewConfigurator(os.OpenFile, osUser)
|
||||||
|
ovpnConf := openvpn.NewConfigurator(logger, os, unix)
|
||||||
|
dnsCrypto := dnscrypto.New(httpClient, "", "")
|
||||||
|
const cacertsPath = "/etc/ssl/certs/ca-certificates.crt"
|
||||||
|
dnsConf := unbound.NewConfigurator(logger, os.OpenFile, dnsCrypto,
|
||||||
|
"/etc/unbound", "/usr/sbin/unbound", cacertsPath)
|
||||||
|
routingConf := routing.NewRouting(logger)
|
||||||
|
firewallConf := firewall.NewConfigurator(logger, routingConf, os.OpenFile)
|
||||||
|
|
||||||
|
fmt.Println(gluetunLogging.Splash(buildInfo))
|
||||||
|
|
||||||
|
printVersions(ctx, logger, map[string]func(ctx context.Context) (string, error){
|
||||||
|
"OpenVPN": ovpnConf.Version,
|
||||||
|
"Unbound": dnsConf.Version,
|
||||||
|
"IPtables": firewallConf.Version,
|
||||||
|
})
|
||||||
|
|
||||||
|
var allSettings configuration.Settings
|
||||||
|
err := allSettings.Read(params.NewEnv(), os, logger.WithPrefix("configuration: "))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info(allSettings.String())
|
||||||
|
|
||||||
|
if err := os.MkdirAll("/tmp/gluetun", 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll("/gluetun", 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO run this in a loop or in openvpn to reload from file without restarting
|
||||||
|
storage := storage.New(logger, os, constants.ServersData)
|
||||||
|
allServers, err := storage.SyncServers(constants.GetAllServers())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should never change
|
||||||
|
puid, pgid := allSettings.System.PUID, allSettings.System.PGID
|
||||||
|
|
||||||
|
const defaultUsername = "nonrootuser"
|
||||||
|
nonRootUsername, err := alpineConf.CreateUser(defaultUsername, puid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if nonRootUsername != defaultUsername {
|
||||||
|
logger.Info("using existing username %s corresponding to user id %d", nonRootUsername, puid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Chown("/etc/unbound", puid, pgid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if allSettings.Firewall.Debug {
|
||||||
|
firewallConf.SetDebug()
|
||||||
|
routingConf.SetDebug()
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultInterface, defaultGateway, err := routingConf.DefaultRoute()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
localSubnet, err := routingConf.LocalSubnet()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultIP, err := routingConf.DefaultIP()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
firewallConf.SetNetworkInformation(defaultInterface, defaultGateway, localSubnet, defaultIP)
|
||||||
|
|
||||||
|
if err := routingConf.Setup(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
routingConf.SetVerbose(false)
|
||||||
|
if err := routingConf.TearDown(); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := firewallConf.SetOutboundSubnets(ctx, allSettings.Firewall.OutboundSubnets); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := routingConf.SetOutboundRoutes(allSettings.Firewall.OutboundSubnets); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ovpnConf.CheckTUN(); err != nil {
|
||||||
|
logger.Warn(err)
|
||||||
|
err = ovpnConf.CreateTUN()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tunnelReadyCh := make(chan struct{})
|
||||||
|
defer close(tunnelReadyCh)
|
||||||
|
|
||||||
|
if allSettings.Firewall.Enabled {
|
||||||
|
err := firewallConf.SetEnabled(ctx, true) // disabled by default
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, vpnPort := range allSettings.Firewall.VPNInputPorts {
|
||||||
|
err = firewallConf.SetAllowedPort(ctx, vpnPort, string(constants.TUN))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, port := range allSettings.Firewall.InputPorts {
|
||||||
|
err = firewallConf.SetAllowedPort(ctx, port, defaultInterface)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} // TODO move inside firewall?
|
||||||
|
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
|
||||||
|
openvpnLooper := openvpn.NewLooper(allSettings.OpenVPN, nonRootUsername, puid, pgid, allServers,
|
||||||
|
ovpnConf, firewallConf, routingConf, logger, httpClient, os.OpenFile, tunnelReadyCh, cancel)
|
||||||
|
wg.Add(1)
|
||||||
|
// wait for restartOpenvpn
|
||||||
|
go openvpnLooper.Run(ctx, wg)
|
||||||
|
|
||||||
|
updaterLooper := updater.NewLooper(allSettings.Updater,
|
||||||
|
allServers, storage, openvpnLooper.SetServers, httpClient, logger)
|
||||||
|
wg.Add(1)
|
||||||
|
// wait for updaterLooper.Restart() or its ticket launched with RunRestartTicker
|
||||||
|
go updaterLooper.Run(ctx, wg)
|
||||||
|
|
||||||
|
unboundLooper := dns.NewLooper(dnsConf, allSettings.DNS, httpClient,
|
||||||
|
logger, nonRootUsername, puid, pgid)
|
||||||
|
wg.Add(1)
|
||||||
|
// wait for unboundLooper.Restart or its ticker launched with RunRestartTicker
|
||||||
|
go unboundLooper.Run(ctx, wg)
|
||||||
|
|
||||||
|
publicIPLooper := publicip.NewLooper(
|
||||||
|
httpClient, logger, allSettings.PublicIP, puid, pgid, os)
|
||||||
|
wg.Add(1)
|
||||||
|
go publicIPLooper.Run(ctx, wg)
|
||||||
|
wg.Add(1)
|
||||||
|
go publicIPLooper.RunRestartTicker(ctx, wg)
|
||||||
|
|
||||||
|
httpProxyLooper := httpproxy.NewLooper(logger, allSettings.HTTPProxy)
|
||||||
|
wg.Add(1)
|
||||||
|
go httpProxyLooper.Run(ctx, wg)
|
||||||
|
|
||||||
|
shadowsocksLooper := shadowsocks.NewLooper(allSettings.ShadowSocks, logger)
|
||||||
|
wg.Add(1)
|
||||||
|
go shadowsocksLooper.Run(ctx, wg)
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go routeReadyEvents(ctx, wg, buildInfo, tunnelReadyCh,
|
||||||
|
unboundLooper, updaterLooper, publicIPLooper, routingConf, logger, httpClient,
|
||||||
|
allSettings.VersionInformation, allSettings.OpenVPN.Provider.PortForwarding.Enabled, openvpnLooper.PortForward,
|
||||||
|
)
|
||||||
|
controlServerAddress := fmt.Sprintf("0.0.0.0:%d", allSettings.ControlServer.Port)
|
||||||
|
controlServerLogging := allSettings.ControlServer.Log
|
||||||
|
httpServer := server.New(controlServerAddress, controlServerLogging,
|
||||||
|
logger, buildInfo, openvpnLooper, unboundLooper, updaterLooper, publicIPLooper)
|
||||||
|
wg.Add(1)
|
||||||
|
go httpServer.Run(ctx, wg)
|
||||||
|
|
||||||
|
healthcheckServer := healthcheck.NewServer(
|
||||||
|
constants.HealthcheckAddress, logger)
|
||||||
|
wg.Add(1)
|
||||||
|
go healthcheckServer.Run(ctx, wg)
|
||||||
|
|
||||||
|
// Start openvpn for the first time in a blocking call
|
||||||
|
// until openvpn is launched
|
||||||
|
_, _ = openvpnLooper.SetStatus(constants.Running) // TODO option to disable with variable
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
|
|
||||||
|
if allSettings.OpenVPN.Provider.PortForwarding.Enabled {
|
||||||
|
logger.Info("Clearing forwarded port status file %s", allSettings.OpenVPN.Provider.PortForwarding.Filepath)
|
||||||
|
if err := os.Remove(allSettings.OpenVPN.Provider.PortForwarding.Filepath); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printVersions(ctx context.Context, logger logging.Logger,
|
||||||
|
versionFunctions map[string]func(ctx context.Context) (string, error)) {
|
||||||
|
const timeout = 5 * time.Second
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
|
defer cancel()
|
||||||
|
for name, f := range versionFunctions {
|
||||||
|
version, err := f(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
} else {
|
||||||
|
logger.Info("%s version: %s", name, version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func routeReadyEvents(ctx context.Context, wg *sync.WaitGroup, buildInfo models.BuildInformation,
|
||||||
|
tunnelReadyCh <-chan struct{},
|
||||||
|
unboundLooper dns.Looper, updaterLooper updater.Looper, publicIPLooper publicip.Looper,
|
||||||
|
routing routing.Routing, logger logging.Logger, httpClient *http.Client,
|
||||||
|
versionInformation, portForwardingEnabled bool, startPortForward func(vpnGateway net.IP)) {
|
||||||
|
defer wg.Done()
|
||||||
|
tickerWg := &sync.WaitGroup{}
|
||||||
|
// for linters only
|
||||||
|
var restartTickerContext context.Context
|
||||||
|
var restartTickerCancel context.CancelFunc = func() {}
|
||||||
|
first := true
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
restartTickerCancel() // for linters only
|
||||||
|
tickerWg.Wait()
|
||||||
|
return
|
||||||
|
case <-tunnelReadyCh: // blocks until openvpn is connected
|
||||||
|
vpnDestination, err := routing.VPNDestinationIP()
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn(err)
|
||||||
|
} else {
|
||||||
|
logger.Info("VPN routing IP address: %s", vpnDestination)
|
||||||
|
}
|
||||||
|
|
||||||
|
if unboundLooper.GetSettings().Enabled {
|
||||||
|
_, _ = unboundLooper.SetStatus(constants.Running)
|
||||||
|
}
|
||||||
|
|
||||||
|
restartTickerCancel() // stop previous restart tickers
|
||||||
|
tickerWg.Wait()
|
||||||
|
restartTickerContext, restartTickerCancel = context.WithCancel(ctx)
|
||||||
|
|
||||||
|
// Runs the Public IP getter job once
|
||||||
|
_, _ = publicIPLooper.SetStatus(constants.Running)
|
||||||
|
if !versionInformation {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if first {
|
||||||
|
first = false
|
||||||
|
message, err := versionpkg.GetMessage(ctx, buildInfo, httpClient)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
} else {
|
||||||
|
logger.Info(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gomnd
|
||||||
|
tickerWg.Add(2)
|
||||||
|
go unboundLooper.RunRestartTicker(restartTickerContext, tickerWg)
|
||||||
|
go updaterLooper.RunRestartTicker(restartTickerContext, tickerWg)
|
||||||
|
if portForwardingEnabled {
|
||||||
|
// vpnGateway required only for PIA
|
||||||
|
vpnGateway, err := routing.VPNLocalGatewayIP()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
logger.Info("VPN gateway IP address: %s", vpnGateway)
|
||||||
|
startPortForward(vpnGateway)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
190
cmd/main.go
190
cmd/main.go
@@ -1,190 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/qdm12/golibs/command"
|
|
||||||
"github.com/qdm12/golibs/files"
|
|
||||||
libhealthcheck "github.com/qdm12/golibs/healthcheck"
|
|
||||||
"github.com/qdm12/golibs/logging"
|
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
"github.com/qdm12/golibs/signals"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/dns"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/env"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/firewall"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/healthcheck"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/openvpn"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/params"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/pia"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/settings"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/shadowsocks"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/splash"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/tinyproxy"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
uid, gid = 1000, 1000
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel, -1)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if libhealthcheck.Mode(os.Args) {
|
|
||||||
if err := healthcheck.HealthCheck(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
paramsReader := params.NewParamsReader(logger)
|
|
||||||
fmt.Println(splash.Splash(paramsReader))
|
|
||||||
e := env.New(logger)
|
|
||||||
client := network.NewClient(15 * time.Second)
|
|
||||||
// Create configurators
|
|
||||||
fileManager := files.NewFileManager()
|
|
||||||
ovpnConf := openvpn.NewConfigurator(logger, fileManager)
|
|
||||||
dnsConf := dns.NewConfigurator(logger, client, fileManager)
|
|
||||||
firewallConf := firewall.NewConfigurator(logger, fileManager)
|
|
||||||
piaConf := pia.NewConfigurator(client, fileManager, firewallConf, logger)
|
|
||||||
tinyProxyConf := tinyproxy.NewConfigurator(fileManager, logger)
|
|
||||||
shadowsocksConf := shadowsocks.NewConfigurator(fileManager, logger)
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
streamMerger := command.NewStreamMerger(ctx)
|
|
||||||
|
|
||||||
e.PrintVersion("OpenVPN", ovpnConf.Version)
|
|
||||||
e.PrintVersion("Unbound", dnsConf.Version)
|
|
||||||
e.PrintVersion("IPtables", firewallConf.Version)
|
|
||||||
e.PrintVersion("TinyProxy", tinyProxyConf.Version)
|
|
||||||
e.PrintVersion("ShadowSocks", shadowsocksConf.Version)
|
|
||||||
|
|
||||||
allSettings, err := settings.GetAllSettings(paramsReader)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
logger.Info(allSettings.String())
|
|
||||||
|
|
||||||
if err := ovpnConf.CheckTUN(); err != nil {
|
|
||||||
logger.Warn(err)
|
|
||||||
err = ovpnConf.CreateTUN()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ovpnConf.WriteAuthFile(allSettings.PIA.User, allSettings.PIA.Password, uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
|
|
||||||
// Temporarily reset chain policies allowing Kubernetes sidecar to
|
|
||||||
// successfully restart the container. Without this, the existing rules will
|
|
||||||
// pre-exist, preventing the nslookup of the PIA region address. These will
|
|
||||||
// simply be redundant at Docker runtime as they will already be set this way
|
|
||||||
// Thanks to @npawelek https://github.com/npawelek
|
|
||||||
err = firewallConf.AcceptAll()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
// Blocking line merging reader for all programs: openvpn, tinyproxy, unbound and shadowsocks
|
|
||||||
logger.Info("Launching standard output merger")
|
|
||||||
err = streamMerger.CollectLines(func(line string) { logger.Info(line) })
|
|
||||||
e.FatalOnError(err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
if allSettings.DNS.Enabled {
|
|
||||||
initialDNSToUse := constants.DNSProviderMapping()[allSettings.DNS.Providers[0]]
|
|
||||||
dnsConf.UseDNSInternally(initialDNSToUse.IPs[0])
|
|
||||||
err = dnsConf.DownloadRootHints(uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = dnsConf.DownloadRootKey(uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = dnsConf.MakeUnboundConf(allSettings.DNS, uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
stream, waitFn, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
go func() {
|
|
||||||
e.FatalOnError(waitFn())
|
|
||||||
}()
|
|
||||||
go streamMerger.Merge("unbound", stream)
|
|
||||||
dnsConf.UseDNSInternally(net.IP{127, 0, 0, 1}) // use Unbound
|
|
||||||
err = dnsConf.UseDNSSystemWide(net.IP{127, 0, 0, 1}) // use Unbound
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = dnsConf.WaitForUnbound()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
VPNIPs, port, err := piaConf.BuildConf(allSettings.PIA.Region, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Encryption, uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
|
|
||||||
defaultInterface, defaultGateway, defaultSubnet, err := firewallConf.GetDefaultRoute()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.AddRoutesVia(allSettings.Firewall.AllowedSubnets, defaultGateway, defaultInterface)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.Clear()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.BlockAll()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.CreateGeneralRules()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.CreateVPNRules(constants.TUN, VPNIPs, defaultInterface, port, allSettings.OpenVPN.NetworkProtocol)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
|
|
||||||
if allSettings.TinyProxy.Enabled {
|
|
||||||
err = tinyProxyConf.MakeConf(allSettings.TinyProxy.LogLevel, allSettings.TinyProxy.Port, allSettings.TinyProxy.User, allSettings.TinyProxy.Password, uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.AllowAnyIncomingOnPort(allSettings.TinyProxy.Port)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
stream, waitFn, err := tinyProxyConf.Start()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
go func() {
|
|
||||||
if err := waitFn(); err != nil {
|
|
||||||
logger.Error(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
go streamMerger.Merge("tinyproxy", stream)
|
|
||||||
}
|
|
||||||
|
|
||||||
if allSettings.ShadowSocks.Enabled {
|
|
||||||
err = shadowsocksConf.MakeConf(allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, uid, gid)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
err = firewallConf.AllowAnyIncomingOnPort(allSettings.ShadowSocks.Port)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
stream, waitFn, err := shadowsocksConf.Start("0.0.0.0", allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, allSettings.ShadowSocks.Log)
|
|
||||||
e.FatalOnError(err)
|
|
||||||
go func() {
|
|
||||||
if err := waitFn(); err != nil {
|
|
||||||
logger.Error(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
go streamMerger.Merge("shadowsocks", stream)
|
|
||||||
}
|
|
||||||
|
|
||||||
if allSettings.PIA.PortForwarding.Enabled {
|
|
||||||
time.AfterFunc(10*time.Second, func() {
|
|
||||||
port, err := piaConf.GetPortForward()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("port forwarding:", err)
|
|
||||||
}
|
|
||||||
if err := piaConf.WritePortForward(allSettings.PIA.PortForwarding.Filepath, port); err != nil {
|
|
||||||
logger.Error("port forwarding:", err)
|
|
||||||
}
|
|
||||||
if err := piaConf.AllowPortForwardFirewall(constants.TUN, port); err != nil {
|
|
||||||
logger.Error("port forwarding:", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
stream, waitFn, err := ovpnConf.Start()
|
|
||||||
e.FatalOnError(err)
|
|
||||||
go streamMerger.Merge("openvpn", stream)
|
|
||||||
go signals.WaitForExit(func(signal string) int {
|
|
||||||
logger.Warn("Caught OS signal %s, shutting down", signal)
|
|
||||||
time.Sleep(100 * time.Millisecond) // wait for other processes to exit
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
e.FatalOnError(waitFn())
|
|
||||||
}
|
|
||||||
1720
doc/logo.svg
Normal file
1720
doc/logo.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 62 KiB |
BIN
doc/logo_256.png
Normal file
BIN
doc/logo_256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -1,37 +1,31 @@
|
|||||||
version: "3.7"
|
version: "3.7"
|
||||||
services:
|
services:
|
||||||
pia:
|
gluetun:
|
||||||
build: https://github.com/qdm12/private-internet-access-docker.git
|
image: qmcgaw/gluetun
|
||||||
image: qmcgaw/private-internet-access
|
container_name: gluetun
|
||||||
container_name: pia
|
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
network_mode: bridge
|
network_mode: bridge
|
||||||
init: true
|
|
||||||
ports:
|
ports:
|
||||||
- 8888:8888/tcp
|
- 8888:8888/tcp # HTTP proxy
|
||||||
- 8388:8388/tcp
|
- 8388:8388/tcp # Shadowsocks
|
||||||
- 8388:8388/udp
|
- 8388:8388/udp # Shadowsocks
|
||||||
|
- 8000:8000/tcp # Built-in HTTP control server
|
||||||
# command:
|
# command:
|
||||||
|
volumes:
|
||||||
|
- /yourpath:/gluetun
|
||||||
|
secrets:
|
||||||
|
- openvpn_user
|
||||||
|
- openvpn_password
|
||||||
environment:
|
environment:
|
||||||
- USER=js89ds7
|
# More variables are available, see the readme table
|
||||||
- PASSWORD=8fd9s239G
|
- VPNSP=private internet access
|
||||||
- ENCRYPTION=strong
|
# Timezone for accurate logs times
|
||||||
- PROTOCOL=udp
|
- TZ=
|
||||||
- REGION=CA Montreal
|
|
||||||
- DOT=on
|
|
||||||
- DOT_PROVIDERS=cloudflare
|
|
||||||
- BLOCK_MALICIOUS=on
|
|
||||||
- BLOCK_SURVEILLANCE=off
|
|
||||||
- BLOCK_ADS=off
|
|
||||||
- UNBLOCK=
|
|
||||||
- EXTRA_SUBNETS=
|
|
||||||
- TINYPROXY=off
|
|
||||||
- TINYPROXY_LOG=Info
|
|
||||||
- TINYPROXY_USER=
|
|
||||||
- TINYPROXY_PASSWORD=
|
|
||||||
- SHADOWSOCKS=off
|
|
||||||
- SHADOWSOCKS_LOG=on
|
|
||||||
- SHADOWSOCKS_PORT=8388
|
|
||||||
- SHADOWSOCKS_PASSWORD=
|
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
openvpn_user:
|
||||||
|
file: ./openvpn_user
|
||||||
|
openvpn_password:
|
||||||
|
file: ./openvpn_password
|
||||||
|
|||||||
18
go.mod
18
go.mod
@@ -1,10 +1,16 @@
|
|||||||
module github.com/qdm12/private-internet-access-docker
|
module github.com/qdm12/gluetun
|
||||||
|
|
||||||
go 1.13
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/kyokomi/emoji v2.1.0+incompatible
|
github.com/fatih/color v1.10.0
|
||||||
github.com/qdm12/golibs v0.0.0-20200208153322-66b2eb719e21
|
github.com/golang/mock v1.4.4
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/kyokomi/emoji v2.2.4+incompatible
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d
|
github.com/qdm12/dns v1.4.0
|
||||||
|
github.com/qdm12/golibs v0.0.0-20210206072445-35759e951561
|
||||||
|
github.com/qdm12/ss-server v0.1.0
|
||||||
|
github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a
|
||||||
|
github.com/stretchr/testify v1.7.0
|
||||||
|
github.com/vishvananda/netlink v1.1.0
|
||||||
|
golang.org/x/sys v0.0.0-20201223074533-0d417f636930
|
||||||
)
|
)
|
||||||
|
|||||||
99
go.sum
99
go.sum
@@ -4,12 +4,23 @@ github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVk
|
|||||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
|
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||||
|
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||||
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
|
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||||
|
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||||
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb h1:D4uzjWwKYQ5XnAvUbuvHW93esHg7F8N/OYeBBcJoTr0=
|
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb h1:D4uzjWwKYQ5XnAvUbuvHW93esHg7F8N/OYeBBcJoTr0=
|
||||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
||||||
@@ -35,41 +46,84 @@ github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi88
|
|||||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||||
github.com/go-openapi/validate v0.17.0 h1:pqoViQz3YLOGIhAmD0N4Lt6pa/3Gnj3ymKqQwq8iS6U=
|
github.com/go-openapi/validate v0.17.0 h1:pqoViQz3YLOGIhAmD0N4Lt6pa/3Gnj3ymKqQwq8iS6U=
|
||||||
github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
|
github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
|
||||||
|
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gotify/go-api-client/v2 v2.0.4 h1:0w8skCr8aLBDKaQDg31LKKHUGF7rt7zdRpR+6cqIAlE=
|
github.com/gotify/go-api-client/v2 v2.0.4 h1:0w8skCr8aLBDKaQDg31LKKHUGF7rt7zdRpR+6cqIAlE=
|
||||||
github.com/gotify/go-api-client/v2 v2.0.4/go.mod h1:VKiah/UK20bXsr0JObE1eBVLW44zbBouzjuri9iwjFU=
|
github.com/gotify/go-api-client/v2 v2.0.4/go.mod h1:VKiah/UK20bXsr0JObE1eBVLW44zbBouzjuri9iwjFU=
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kyokomi/emoji v2.1.0+incompatible h1:+DYU2RgpI6OHG4oQkM5KlqD3Wd3UPEsX8jamTo1Mp6o=
|
github.com/kyokomi/emoji v2.2.4+incompatible h1:np0woGKwx9LiHAQmwZx79Oc0rHpNw3o+3evou4BEPv4=
|
||||||
github.com/kyokomi/emoji v2.1.0+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
|
github.com/kyokomi/emoji v2.2.4+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
|
||||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
|
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
|
||||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||||
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||||
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||||
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
||||||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
|
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||||
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee h1:P6U24L02WMfj9ymZTxl7CxS73JC99x3ukk+DBkgQGQs=
|
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee h1:P6U24L02WMfj9ymZTxl7CxS73JC99x3ukk+DBkgQGQs=
|
||||||
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY=
|
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
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/qdm12/golibs v0.0.0-20200208153322-66b2eb719e21 h1:Nza/Ar6tPYhDzkiNzbaJZHl4+GUXTqbtjGXuWenkqpQ=
|
github.com/qdm12/dns v1.4.0 h1:P8kVMGo7yIEZSk18fA9XQh9faL1CW20aHosWP064MAA=
|
||||||
github.com/qdm12/golibs v0.0.0-20200208153322-66b2eb719e21/go.mod h1:YULaFjj6VGmhjak6f35sUWwEleHUmngN5IQ3kdvd6XE=
|
github.com/qdm12/dns v1.4.0/go.mod h1:WUY4/U8Z2O8888DPrahrIBv8GdYeoIcEy4aUDecZ+UM=
|
||||||
|
github.com/qdm12/golibs v0.0.0-20201227203847-2fd99ffdfdba/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc=
|
||||||
|
github.com/qdm12/golibs v0.0.0-20210124192933-79a950eaf217 h1:/eMBq0vbc/KmVPXbwLfssp547pp6APRS1x/JNmPvm0s=
|
||||||
|
github.com/qdm12/golibs v0.0.0-20210124192933-79a950eaf217/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc=
|
||||||
|
github.com/qdm12/golibs v0.0.0-20210206072445-35759e951561 h1:YgdQYYj4cEq8jK9TWCItlOOLfmDMVMajcp0YGVCW7cA=
|
||||||
|
github.com/qdm12/golibs v0.0.0-20210206072445-35759e951561/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc=
|
||||||
|
github.com/qdm12/ss-server v0.1.0 h1:WV9MkHCDEWRwe4WpnYFeR/zcZAxYoTbfntLDnw9AQ50=
|
||||||
|
github.com/qdm12/ss-server v0.1.0/go.mod h1:ABVUkxubboL3vqBkOwDV9glX1/x7SnYrckBe5d+M/zw=
|
||||||
|
github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a h1:gkyP+gMEeBgMgyRYGrVNcoy6cL1065IvXsyfB6xboIc=
|
||||||
|
github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a/go.mod h1:bbJGxEYCnsA8WU4vBcXYU6mOoHyzdP458FIKP4mfLJM=
|
||||||
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||||
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
|
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||||
|
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||||
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
|
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
|
||||||
@@ -78,36 +132,61 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEa
|
|||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
||||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||||
|
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
|
||||||
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
|
||||||
|
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||||
|
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||||
|
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|||||||
23
internal/alpine/alpine.go
Normal file
23
internal/alpine/alpine.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Package alpine defines a configurator to interact with the Alpine operating system.
|
||||||
|
package alpine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
"github.com/qdm12/golibs/os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Configurator interface {
|
||||||
|
CreateUser(username string, uid int) (createdUsername string, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type configurator struct {
|
||||||
|
openFile os.OpenFileFunc
|
||||||
|
osUser user.OSUser
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfigurator(openFile os.OpenFileFunc, osUser user.OSUser) Configurator {
|
||||||
|
return &configurator{
|
||||||
|
openFile: openFile,
|
||||||
|
osUser: osUser,
|
||||||
|
}
|
||||||
|
}
|
||||||
41
internal/alpine/users.go
Normal file
41
internal/alpine/users.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package alpine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateUser creates a user in Alpine with the given UID.
|
||||||
|
func (c *configurator) CreateUser(username string, uid int) (createdUsername string, err error) {
|
||||||
|
UIDStr := fmt.Sprintf("%d", uid)
|
||||||
|
u, err := c.osUser.LookupID(UIDStr)
|
||||||
|
_, unknownUID := err.(user.UnknownUserIdError)
|
||||||
|
if err != nil && !unknownUID {
|
||||||
|
return "", fmt.Errorf("cannot create user: %w", err)
|
||||||
|
} else if u != nil {
|
||||||
|
if u.Username == username {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return u.Username, nil
|
||||||
|
}
|
||||||
|
u, err = c.osUser.Lookup(username)
|
||||||
|
_, unknownUsername := err.(user.UnknownUserError)
|
||||||
|
if err != nil && !unknownUsername {
|
||||||
|
return "", fmt.Errorf("cannot create user: %w", err)
|
||||||
|
} else if u != nil {
|
||||||
|
return "", fmt.Errorf("cannot create user: user with name %s already exists for ID %s instead of %d",
|
||||||
|
username, u.Uid, uid)
|
||||||
|
}
|
||||||
|
file, err := c.openFile("/etc/passwd", os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("cannot create user: %w", err)
|
||||||
|
}
|
||||||
|
s := fmt.Sprintf("%s:x:%d:::/dev/null:/sbin/nologin\n", username, uid)
|
||||||
|
_, err = file.WriteString(s)
|
||||||
|
if err != nil {
|
||||||
|
_ = file.Close()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return username, file.Close()
|
||||||
|
}
|
||||||
7
internal/cli/ci.go
Normal file
7
internal/cli/ci.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
func (c *cli) CI(context context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
21
internal/cli/cli.go
Normal file
21
internal/cli/cli.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Package cli defines an interface CLI to run command line operations.
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CLI interface {
|
||||||
|
ClientKey(args []string, openFile os.OpenFileFunc) error
|
||||||
|
HealthCheck(ctx context.Context) error
|
||||||
|
OpenvpnConfig(os os.OS) error
|
||||||
|
Update(ctx context.Context, args []string, os os.OS) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type cli struct{}
|
||||||
|
|
||||||
|
func New() CLI {
|
||||||
|
return &cli{}
|
||||||
|
}
|
||||||
41
internal/cli/clientkey.go
Normal file
41
internal/cli/clientkey.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) ClientKey(args []string, openFile os.OpenFileFunc) error {
|
||||||
|
flagSet := flag.NewFlagSet("clientkey", flag.ExitOnError)
|
||||||
|
filepath := flagSet.String("path", constants.ClientKey, "file path to the client.key file")
|
||||||
|
if err := flagSet.Parse(args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file, err := openFile(*filepath, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
_ = file.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := file.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s := string(data)
|
||||||
|
s = strings.ReplaceAll(s, "\n", "")
|
||||||
|
s = strings.ReplaceAll(s, "\r", "")
|
||||||
|
s = strings.TrimPrefix(s, "-----BEGIN PRIVATE KEY-----")
|
||||||
|
s = strings.TrimSuffix(s, "-----END PRIVATE KEY-----")
|
||||||
|
fmt.Println(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
20
internal/cli/healthcheck.go
Normal file
20
internal/cli/healthcheck.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/healthcheck"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) HealthCheck(ctx context.Context) error {
|
||||||
|
const timeout = 10 * time.Second
|
||||||
|
httpClient := &http.Client{Timeout: timeout}
|
||||||
|
healthchecker := healthcheck.NewChecker(httpClient)
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
|
defer cancel()
|
||||||
|
const url = "http://" + constants.HealthcheckAddress
|
||||||
|
return healthchecker.Check(ctx, url)
|
||||||
|
}
|
||||||
41
internal/cli/openvpnconfig.go
Normal file
41
internal/cli/openvpnconfig.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/configuration"
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/provider"
|
||||||
|
"github.com/qdm12/gluetun/internal/storage"
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) OpenvpnConfig(os os.OS) error {
|
||||||
|
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var allSettings configuration.Settings
|
||||||
|
err = allSettings.Read(params.NewEnv(), os, logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
allServers, err := storage.New(logger, os, constants.ServersData).
|
||||||
|
SyncServers(constants.GetAllServers())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
providerConf := provider.New(allSettings.OpenVPN.Provider.Name, allServers, time.Now)
|
||||||
|
connection, err := providerConf.GetOpenVPNConnection(allSettings.OpenVPN.Provider.ServerSelection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lines := providerConf.BuildConf(connection, "nonroortuser", allSettings.OpenVPN)
|
||||||
|
fmt.Println(strings.Join(lines, "\n"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
64
internal/cli/update.go
Normal file
64
internal/cli/update.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/configuration"
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/storage"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater"
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) Update(ctx context.Context, args []string, os os.OS) error {
|
||||||
|
options := configuration.Updater{CLI: true}
|
||||||
|
var flushToFile bool
|
||||||
|
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
|
||||||
|
flagSet.BoolVar(&flushToFile, "file", false, "Write results to /gluetun/servers.json (for end users)")
|
||||||
|
flagSet.BoolVar(&options.Stdout, "stdout", false, "Write results to console to modify the program (for maintainers)")
|
||||||
|
flagSet.StringVar(&options.DNSAddress, "dns", "1.1.1.1", "DNS resolver address to use")
|
||||||
|
flagSet.BoolVar(&options.Cyberghost, "cyberghost", false, "Update Cyberghost servers")
|
||||||
|
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
|
||||||
|
flagSet.BoolVar(&options.Nordvpn, "nordvpn", false, "Update Nordvpn servers")
|
||||||
|
flagSet.BoolVar(&options.PIA, "pia", false, "Update Private Internet Access post-summer 2020 servers")
|
||||||
|
flagSet.BoolVar(&options.Privado, "privado", false, "Update Privado servers")
|
||||||
|
flagSet.BoolVar(&options.Purevpn, "purevpn", false, "Update Purevpn servers")
|
||||||
|
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
|
||||||
|
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")
|
||||||
|
flagSet.BoolVar(&options.Windscribe, "windscribe", false, "Update Windscribe servers")
|
||||||
|
if err := flagSet.Parse(args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !flushToFile && !options.Stdout {
|
||||||
|
return fmt.Errorf("at least one of -file or -stdout must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
const clientTimeout = 10 * time.Second
|
||||||
|
httpClient := &http.Client{Timeout: clientTimeout}
|
||||||
|
storage := storage.New(logger, os, constants.ServersData)
|
||||||
|
currentServers, err := storage.SyncServers(constants.GetAllServers())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot update servers: %w", err)
|
||||||
|
}
|
||||||
|
updater := updater.New(options, httpClient, currentServers, logger)
|
||||||
|
allServers, err := updater.UpdateServers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if flushToFile {
|
||||||
|
if err := storage.FlushToFile(allServers); err != nil {
|
||||||
|
return fmt.Errorf("cannot update servers: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
3
internal/configuration/configuration.go
Normal file
3
internal/configuration/configuration.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package configuration reads initial settings from environment variables
|
||||||
|
// and secret files.
|
||||||
|
package configuration
|
||||||
6
internal/configuration/constants.go
Normal file
6
internal/configuration/constants.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
const (
|
||||||
|
lastIndent = "|--"
|
||||||
|
indent = " "
|
||||||
|
)
|
||||||
107
internal/configuration/cyberghost.go
Normal file
107
internal/configuration/cyberghost.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) cyberghostLines() (lines []string) {
|
||||||
|
lines = append(lines, lastIndent+"Server group: "+settings.ServerSelection.Group)
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.ExtraConfigOptions.ClientKey != "" {
|
||||||
|
lines = append(lines, lastIndent+"Client key is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.ExtraConfigOptions.ClientCertificate != "" {
|
||||||
|
lines = append(lines, lastIndent+"Client certificate is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readCyberghost(r reader) (err error) {
|
||||||
|
settings.Name = constants.Cyberghost
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ExtraConfigOptions.ClientKey, err = readCyberghostClientKey(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ExtraConfigOptions.ClientCertificate, err = readCyberghostClientCertificate(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Group, err = r.env.Inside("CYBERGHOST_GROUP",
|
||||||
|
constants.CyberghostGroupChoices(), params.Default("Premium UDP Europe"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.CyberghostRegionChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readCyberghostClientKey(r reader) (clientKey string, err error) {
|
||||||
|
b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTKEY", constants.ClientKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return extractClientKey(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractClientKey(b []byte) (key string, err error) {
|
||||||
|
pemBlock, _ := pem.Decode(b)
|
||||||
|
if pemBlock == nil {
|
||||||
|
return "", fmt.Errorf("cannot decode PEM block from client key")
|
||||||
|
}
|
||||||
|
parsedBytes := pem.EncodeToMemory(pemBlock)
|
||||||
|
s := string(parsedBytes)
|
||||||
|
s = strings.ReplaceAll(s, "\n", "")
|
||||||
|
s = strings.TrimPrefix(s, "-----BEGIN PRIVATE KEY-----")
|
||||||
|
s = strings.TrimSuffix(s, "-----END PRIVATE KEY-----")
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readCyberghostClientCertificate(r reader) (clientCertificate string, err error) {
|
||||||
|
b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTCRT", constants.ClientCertificate)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return extractClientCertificate(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractClientCertificate(b []byte) (certificate string, err error) {
|
||||||
|
pemBlock, _ := pem.Decode(b)
|
||||||
|
if pemBlock == nil {
|
||||||
|
return "", fmt.Errorf("cannot decode PEM block from client certificate")
|
||||||
|
}
|
||||||
|
parsedBytes := pem.EncodeToMemory(pemBlock)
|
||||||
|
s := string(parsedBytes)
|
||||||
|
s = strings.ReplaceAll(s, "\n", "")
|
||||||
|
s = strings.TrimPrefix(s, "-----BEGIN CERTIFICATE-----")
|
||||||
|
s = strings.TrimSuffix(s, "-----END CERTIFICATE-----")
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
175
internal/configuration/cyberghost_test.go
Normal file
175
internal/configuration/cyberghost_test.go
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_extractClientKey(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
const validPEM = `
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCrQDrezCptkWxX
|
||||||
|
ywm3KdXtvti+rPF3vfzOmXRKiKXDMpMxzoiaD5Wspirxxjr4C+B14xTwZjJZfxJL
|
||||||
|
2HpPdOeBmA5tmAoGUESspnzxR/N1T4Uggx0vlAzFo0UZ0sutV6CJK19Kk38REwlG
|
||||||
|
AB8gl6JYeSUuu6qREjrLVwFRH72acvC/p4jBki/MjAfEaeHc0yDJT9jpjpchw+Hx
|
||||||
|
Ymy+1BnfNTAfGDdTVx9qWb+ByQ7xfvzuD9AOeqiWApDzZIuDDsaWn2orv+syoJVo
|
||||||
|
rV52/F+75zks6+fzQ+0sotBlRyvsZKGi80F89RIHwG+5LNSuRDWnVvrwv1oc6V2/
|
||||||
|
lMidwT7yb0kXt0IRW6JzbaHyB2LkPazBlr6IPNupk83x9t2Buw0HI2SQKHMKOChU
|
||||||
|
i2/906yLUOo3QpAi3Wk1c/Xu9DvGR/pOA15WCakiAfG3Fq6hUxNncmpOMeOLF/ez
|
||||||
|
L19jZ3KA4E2Te4+GA0NYlXgkDbsIILWapHwqHXcDukynHisr7RawjrvXoLyasm4L
|
||||||
|
O66aNXK9wtipSMDA7tdlQP6Xe9bHflDHxwreiuEGxnrsvLU7LHBWdD7UT2/u8zdr
|
||||||
|
pimqi4L7W5p5aOBMn8jSVCO9+4CAxiLlc2qx5vb4/EPMsdQfacYP7vY9iVh/qPi3
|
||||||
|
bcUVGUlg8wAJDrTksxU1K3FVR7BEPwIDAQABAoICAAhyrbTJ+5nWH7MhCASqIqyM
|
||||||
|
yqJ1Y6AVlkAW397BaPP9Lbe6SZDYDfkrZVjx/3y3EUafgivtzrQNibiGIFqFGNqS
|
||||||
|
xrtvUadIFGsz91vrwb3aw2V8MldjhVHGoSUJ+hQ+C2RY6GWEazNLbhyu6tovwMl+
|
||||||
|
iHAKv/pSHOZlD2KSH0dcPjYmLJ/n90Wu7r8ovgSnwalMsBWtfBUlVaMTyOuNCQ2y
|
||||||
|
0QHnrusElD8p2EGtynftXMrdqtTcBi8IR2BKaHt5oiBSEum/mPmxZE16p/tUreBW
|
||||||
|
IsLtjE663htimMc2QJtzx2mDeIqSiGYrfxdyd7d1E/SCXPS9a9ObS42k6FSn8NPu
|
||||||
|
K5kN6fPV5EDM2CqKEt9QZPlyrjZIuffOZtJj0xPuTwhRle4SOtyjn2c/vsv9Fkrp
|
||||||
|
B6B1v7T4+SSOIedOYkL+FP/IexMNG/ZTB5Y2hrZ03JW9RGpFAa4//qGG2qUCR3hE
|
||||||
|
rVS6v58qO/3+TCFSn/TI8AfcTcJbes3yTbVyLH6NAjATfYqJDJJFf+PG0qKc8q1N
|
||||||
|
KvXmT+x4JiBBM32cOg11GPflxIZSKi9He50hnPGnC042N06ba/pkUPG49XwE37hn
|
||||||
|
kIGmcFGcDIMDTEZnPBogPFqGpepYdwGWxbadRiUoX2wgurHRRmA0YM32MjVky9C1
|
||||||
|
12Q/Jy9PIk/qdjYdWfAhAoIBAQDcvxfUx7MKMFgYYm4E51X+7B9QoxdhVaxcoVgK
|
||||||
|
VwfvedsLi0Bk1B1JVSXqnNfyDZbpxFz2v5Xd/dSit2rjnfBm+DoJYN9ZNnrbIH+s
|
||||||
|
qsO1DuHZvMZlRDJbpt7PpVH/pcf7rEWRY+avkMMsiGwI/ruDs17eu7jULeG7N4jb
|
||||||
|
kh1mdvF7K56O6Xe8jGJu5qaOPRWOkABK1cEOjQ5hB1iAwO/ua5hehP87SvbYzIhz
|
||||||
|
nQTE3AqTWgWbIyC4R85U7tS9hsXnSQ/ICM9pWcyN0Y667LwR2tX0QKl5M/YoM0sG
|
||||||
|
mw+VQED8O2R45jTzSAcox77dRg55Pp3Xexsp2iVvaTIeAaevAoIBAQDGmZS1gFO4
|
||||||
|
TEgQXHdmibLizDUHLuw662GC+3Hilx+nZBZtWOc6t8yquUyggSKQmBDiKAf0ipMe
|
||||||
|
xFao+5I3StJJ2P4Vel95Vcu8KgqCF736Q1iNgDHuW8ho8e0y+YE371x5co3POGC0
|
||||||
|
SfbcnRTXQx2+wWXzZDh+KtnaDUyDN12/qCIUyAuSVLwEM28ZFM3qadG1aUdCB5oe
|
||||||
|
o8jfgsg6YSukm4uE/tuI3/wAI7FkaCqvt/zkLauRff5FcNa7os4EKtNnGfebxscP
|
||||||
|
yFYpMsW9VI0rfmYz02gho33lnofs4o8x/gxh6t5zfVbsZ7vUiSDJBahWboG9aE99
|
||||||
|
OY2TKb6ibsBxAoIBAQChDBVR2oPnqg+Lcrw7fZ8Cxbeu992F2KBQUDHQEWCruSYy
|
||||||
|
zNwk84+OQb3Q5a6yXHG+iNEd//ZRp+8q60/jUgXiybRlxTQNfS6ykYo0Kb1wabQi
|
||||||
|
S5Qeq1tl/F9P9JfXQFafaTaz9MOHUMDjy3+uLFIXqpRLQX995R9rm/+P2ZDzgVF5
|
||||||
|
///E2dXOTElACax3117TzIE6F6qqeASGi3ppLNmfAwZ95t/inTVsRARE/MhO6w4Y
|
||||||
|
JLQ0U7N6XoDM/BVfVGUr8OS/lpXjkW0oBjvwaehnylUPxuEdmOg8ufdBkX0T8XW3
|
||||||
|
z4jkn2cAGouGl/vKqWLD2AgF/j16Ejn/hyrWM3TnAoIBAA6lSssrwIDJ11KljwSX
|
||||||
|
yQJirtJtymv56cIACwD7xhDRF7pOoRa6cTRx383CWCszm6Mh8pw9D+Zn8kAZ9Ulw
|
||||||
|
khtyDiLFWH8ZLaIds5Kub4siJkihGI2MZTYgCS8GKVpXo4ktQnnynWcOQU85okzR
|
||||||
|
nULw/jS5wlTDkjc7XdYbYiV9H65KplfPOeJRbLL7zsensBhhwCiFaP8zct/QxDVR
|
||||||
|
7yb/dYWESepJIktcVnuiFuvIdLTbDVj4YqT6UkuaEPlLszVaO+FYAlwOmRQGs4Bn
|
||||||
|
2NVJR/4wa/B3HxSs4Tc96fN02bLq4CbCKoPajoZ46lsIuMZO9fBi3eHNObyNiopu
|
||||||
|
AnECggEBAJiJ0tK/PGh+Q9uv57Z4QcmbawoxMQW1qK/rLYwacYsSpzo8VhbZf+Jh
|
||||||
|
8biMg9AIQsLWnqmB3gmndePArGXkSxnilRozNLaeclTZy7rh00BctTEfgee4Kxdi
|
||||||
|
JKkJlVK0CE8I6txVRqkoOMyxsk1kRZ4l2yW2nxzyWlJKwvD75x2PQ6xWvpLAggyn
|
||||||
|
q00I3MzNIgR123jytN1NyC7l+mnGoC23ToXM7B3/PQjGYTq3jawKomrX1cmwzKBT
|
||||||
|
+pzjtJSWvMeUEZQS1PpOhxpPBRHagdKXt+ug2DqDtU6rfpDGtTBh5QNkg5SA7lxZ
|
||||||
|
zZjrL52saevO25cigVl+hxcnY8DTpbk=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
const validKeyString = "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCrQDrezCptkWxXywm3KdXtvti+rPF3vfzOmXRKiKXDMpMxzoiaD5Wspirxxjr4C+B14xTwZjJZfxJL2HpPdOeBmA5tmAoGUESspnzxR/N1T4Uggx0vlAzFo0UZ0sutV6CJK19Kk38REwlGAB8gl6JYeSUuu6qREjrLVwFRH72acvC/p4jBki/MjAfEaeHc0yDJT9jpjpchw+HxYmy+1BnfNTAfGDdTVx9qWb+ByQ7xfvzuD9AOeqiWApDzZIuDDsaWn2orv+syoJVorV52/F+75zks6+fzQ+0sotBlRyvsZKGi80F89RIHwG+5LNSuRDWnVvrwv1oc6V2/lMidwT7yb0kXt0IRW6JzbaHyB2LkPazBlr6IPNupk83x9t2Buw0HI2SQKHMKOChUi2/906yLUOo3QpAi3Wk1c/Xu9DvGR/pOA15WCakiAfG3Fq6hUxNncmpOMeOLF/ezL19jZ3KA4E2Te4+GA0NYlXgkDbsIILWapHwqHXcDukynHisr7RawjrvXoLyasm4LO66aNXK9wtipSMDA7tdlQP6Xe9bHflDHxwreiuEGxnrsvLU7LHBWdD7UT2/u8zdrpimqi4L7W5p5aOBMn8jSVCO9+4CAxiLlc2qx5vb4/EPMsdQfacYP7vY9iVh/qPi3bcUVGUlg8wAJDrTksxU1K3FVR7BEPwIDAQABAoICAAhyrbTJ+5nWH7MhCASqIqyMyqJ1Y6AVlkAW397BaPP9Lbe6SZDYDfkrZVjx/3y3EUafgivtzrQNibiGIFqFGNqSxrtvUadIFGsz91vrwb3aw2V8MldjhVHGoSUJ+hQ+C2RY6GWEazNLbhyu6tovwMl+iHAKv/pSHOZlD2KSH0dcPjYmLJ/n90Wu7r8ovgSnwalMsBWtfBUlVaMTyOuNCQ2y0QHnrusElD8p2EGtynftXMrdqtTcBi8IR2BKaHt5oiBSEum/mPmxZE16p/tUreBWIsLtjE663htimMc2QJtzx2mDeIqSiGYrfxdyd7d1E/SCXPS9a9ObS42k6FSn8NPuK5kN6fPV5EDM2CqKEt9QZPlyrjZIuffOZtJj0xPuTwhRle4SOtyjn2c/vsv9FkrpB6B1v7T4+SSOIedOYkL+FP/IexMNG/ZTB5Y2hrZ03JW9RGpFAa4//qGG2qUCR3hErVS6v58qO/3+TCFSn/TI8AfcTcJbes3yTbVyLH6NAjATfYqJDJJFf+PG0qKc8q1NKvXmT+x4JiBBM32cOg11GPflxIZSKi9He50hnPGnC042N06ba/pkUPG49XwE37hnkIGmcFGcDIMDTEZnPBogPFqGpepYdwGWxbadRiUoX2wgurHRRmA0YM32MjVky9C112Q/Jy9PIk/qdjYdWfAhAoIBAQDcvxfUx7MKMFgYYm4E51X+7B9QoxdhVaxcoVgKVwfvedsLi0Bk1B1JVSXqnNfyDZbpxFz2v5Xd/dSit2rjnfBm+DoJYN9ZNnrbIH+sqsO1DuHZvMZlRDJbpt7PpVH/pcf7rEWRY+avkMMsiGwI/ruDs17eu7jULeG7N4jbkh1mdvF7K56O6Xe8jGJu5qaOPRWOkABK1cEOjQ5hB1iAwO/ua5hehP87SvbYzIhznQTE3AqTWgWbIyC4R85U7tS9hsXnSQ/ICM9pWcyN0Y667LwR2tX0QKl5M/YoM0sGmw+VQED8O2R45jTzSAcox77dRg55Pp3Xexsp2iVvaTIeAaevAoIBAQDGmZS1gFO4TEgQXHdmibLizDUHLuw662GC+3Hilx+nZBZtWOc6t8yquUyggSKQmBDiKAf0ipMexFao+5I3StJJ2P4Vel95Vcu8KgqCF736Q1iNgDHuW8ho8e0y+YE371x5co3POGC0SfbcnRTXQx2+wWXzZDh+KtnaDUyDN12/qCIUyAuSVLwEM28ZFM3qadG1aUdCB5oeo8jfgsg6YSukm4uE/tuI3/wAI7FkaCqvt/zkLauRff5FcNa7os4EKtNnGfebxscPyFYpMsW9VI0rfmYz02gho33lnofs4o8x/gxh6t5zfVbsZ7vUiSDJBahWboG9aE99OY2TKb6ibsBxAoIBAQChDBVR2oPnqg+Lcrw7fZ8Cxbeu992F2KBQUDHQEWCruSYyzNwk84+OQb3Q5a6yXHG+iNEd//ZRp+8q60/jUgXiybRlxTQNfS6ykYo0Kb1wabQiS5Qeq1tl/F9P9JfXQFafaTaz9MOHUMDjy3+uLFIXqpRLQX995R9rm/+P2ZDzgVF5///E2dXOTElACax3117TzIE6F6qqeASGi3ppLNmfAwZ95t/inTVsRARE/MhO6w4YJLQ0U7N6XoDM/BVfVGUr8OS/lpXjkW0oBjvwaehnylUPxuEdmOg8ufdBkX0T8XW3z4jkn2cAGouGl/vKqWLD2AgF/j16Ejn/hyrWM3TnAoIBAA6lSssrwIDJ11KljwSXyQJirtJtymv56cIACwD7xhDRF7pOoRa6cTRx383CWCszm6Mh8pw9D+Zn8kAZ9UlwkhtyDiLFWH8ZLaIds5Kub4siJkihGI2MZTYgCS8GKVpXo4ktQnnynWcOQU85okzRnULw/jS5wlTDkjc7XdYbYiV9H65KplfPOeJRbLL7zsensBhhwCiFaP8zct/QxDVR7yb/dYWESepJIktcVnuiFuvIdLTbDVj4YqT6UkuaEPlLszVaO+FYAlwOmRQGs4Bn2NVJR/4wa/B3HxSs4Tc96fN02bLq4CbCKoPajoZ46lsIuMZO9fBi3eHNObyNiopuAnECggEBAJiJ0tK/PGh+Q9uv57Z4QcmbawoxMQW1qK/rLYwacYsSpzo8VhbZf+Jh8biMg9AIQsLWnqmB3gmndePArGXkSxnilRozNLaeclTZy7rh00BctTEfgee4KxdiJKkJlVK0CE8I6txVRqkoOMyxsk1kRZ4l2yW2nxzyWlJKwvD75x2PQ6xWvpLAggynq00I3MzNIgR123jytN1NyC7l+mnGoC23ToXM7B3/PQjGYTq3jawKomrX1cmwzKBT+pzjtJSWvMeUEZQS1PpOhxpPBRHagdKXt+ug2DqDtU6rfpDGtTBh5QNkg5SA7lxZzZjrL52saevO25cigVl+hxcnY8DTpbk=" //nolint:lll
|
||||||
|
testCases := map[string]struct {
|
||||||
|
b []byte
|
||||||
|
key string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
"no input": {
|
||||||
|
err: fmt.Errorf("cannot decode PEM block from client key"),
|
||||||
|
},
|
||||||
|
"bad input": {
|
||||||
|
b: []byte{1, 2, 3},
|
||||||
|
err: fmt.Errorf("cannot decode PEM block from client key"),
|
||||||
|
},
|
||||||
|
"valid key": {
|
||||||
|
b: []byte(validPEM),
|
||||||
|
key: validKeyString,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
key, err := extractClientKey(testCase.b)
|
||||||
|
if testCase.err != nil {
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, testCase.key, key)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_extractClientCertificate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
const validPEM = `
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGrDCCBJSgAwIBAgIEAdTnfTANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJS
|
||||||
|
TzESMBAGA1UEBxMJQnVjaGFyZXN0MRgwFgYDVQQKEw9DeWJlckdob3N0IFMuQS4x
|
||||||
|
GzAZBgNVBAMTEkN5YmVyR2hvc3QgUm9vdCBDQTEhMB8GCSqGSIb3DQEJARYSaW5m
|
||||||
|
b0BjeWJlcmdob3N0LnJvMB4XDTIwMDcwNDE1MjkzNloXDTMwMDcwMjE1MjkzNlow
|
||||||
|
fTELMAkGA1UEBhMCUk8xEjAQBgNVBAcMCUJ1Y2hhcmVzdDEYMBYGA1UECgwPQ3li
|
||||||
|
ZXJHaG9zdCBTLkEuMR0wGwYDVQQDDBRjLmoua2xhdmVyQGdtYWlsLmNvbTEhMB8G
|
||||||
|
CSqGSIb3DQEJARYSaW5mb0BjeWJlcmdob3N0LnJvMIICIjANBgkqhkiG9w0BAQEF
|
||||||
|
AAOCAg8AMIICCgKCAgEAobp2NlGUHMNBe08YEOnVG3QJjF3ZaXbRhE/II9rmtgJT
|
||||||
|
NZtDohGChvFlNRsExKzVrKxHCeuJkVffwzQ6fYk4/M1RdYLJUh0UVw3e4WdApw8E
|
||||||
|
7TJZxDYm4SHQNXUvt1Rt5TjslcXxIpDZgrMSc/kHROYEL9tdgdzPZErUJehXyJPh
|
||||||
|
EzIrzmAJh501x7WwKPz9ctSVlItyavqEWFF2vyUa6X9DYmD9mQTz5c+VXNO5DkXm
|
||||||
|
PFBIaEVDnvFtcjGJ56yEvFnWVukL+OUX7ezowrIOFOcp9udjgpeiHq+XvsQ6ER0D
|
||||||
|
Jt25MiEId3NjkxtZ8BitDftTcLN/kt81hWKT7adMVc3kpIZ80cxrwRCttMd7sHAz
|
||||||
|
KI9u7pMxv10eUOsIEY87ewBe3l6KvEnjA+9uIjim6gLLebDIaEH50Ee9PzNJ8fqQ
|
||||||
|
2u54Ab4bt00/H1sUnJ6Ss/+WsQDOK1BsPRKKcnHZntOlHrs2Tu5+txKNU2cOapI8
|
||||||
|
SjVULUNKrRXASbpfWnLUfri/HO742bJb/TjkOJcOxta3hTPFAhaRWBusVlB41XVH
|
||||||
|
euH5DAhugYXeSNK6/6Ul8YvKUNH/7QbxuGIGXfth19Xl4QLI1umyEjZopSlt3tOi
|
||||||
|
O2V1soVNSQCCfxXVoCTMESMLjhkjWdmBDhdy2GTW7S4YoJfqVKiS18rYkN7I4ZMC
|
||||||
|
AwEAAaOCATQwggEwMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMDQGCWCGSAGG+EIB
|
||||||
|
DQQnFiVDeWJlckdob3N0IEdlbmVyYXRlZCBVc2VyIENlcnRpZmljYXRlMBEGCWCG
|
||||||
|
SAGG+EIBAQQEAwIHgDAdBgNVHQ4EFgQULwUtU5s6pL2NN9gPeEnKX0dhwiswga0G
|
||||||
|
A1UdIwSBpTCBooAU6tdK1g/He5qzjeAoM5eHt4in9iWhf6R9MHsxCzAJBgNVBAYT
|
||||||
|
AlJPMRIwEAYDVQQHEwlCdWNoYXJlc3QxGDAWBgNVBAoTD0N5YmVyR2hvc3QgUy5B
|
||||||
|
LjEbMBkGA1UEAxMSQ3liZXJHaG9zdCBSb290IENBMSEwHwYJKoZIhvcNAQkBFhJp
|
||||||
|
bmZvQGN5YmVyZ2hvc3Qucm+CCQCcVButZsQ0uzANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||||
|
ystGIMYhQWaEdTqlnLCytrr8657t+PuidZMNNIaPB3wN2Fi2xKf14DTg03mqxjmP
|
||||||
|
Pb+f+PVNIOV5PdWD4jcQwOP1GEboGV0DFzlRGeAtDcvKwdee4oASJbZq1CETqDao
|
||||||
|
hQTxKEWC+UBk2F36nOaEI6Sab+Mb4cR9//PAwvzOqrXuGF5NuIOX7eFtCMQSgQq6
|
||||||
|
lRRqTQjekm0Dxigx4JA92Jo2qZRwCJ0T3IXBJGL831HCFJbDWv8PV3lsfFb/i2+v
|
||||||
|
r54uywFQVWWp18dYi97gipfuQ4zRg2Ldx5aXSmnhhKpg5ioZvtk043QofF12YORh
|
||||||
|
obElqavRbvvhZvlCouvcuoq9QKi7IPe5SJZkZ1X7ezMesCwBzwFpt6vRUAcslsNF
|
||||||
|
bcYS1iSENlY/PTcDqBhbKuc9yAhq+/aUgaY/8VF5RWVzSRZufbf3BPwOkE4K0Uyb
|
||||||
|
aobO/YX0JOkCacAD+4tdR6YSXNIMMRAOCBQvxbxFXaHzhwhzBAjdsC56FrJKwXvQ
|
||||||
|
rRLU3tF4P0zFMeNTay8uTtUXugDK7EnklLESuYdpUJ8bUMlAUhJBi6UFI9/icMud
|
||||||
|
xXvLRvhnBW9EtKib5JnVFUovcEUt+3EJbyst05nkL4YPjQS4TC9DHdo5SyRAy1Tp
|
||||||
|
iOCYTbretAFZRhh6ycUN5hBeN8GMQxiMreMtDV4PEIQ=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
`
|
||||||
|
const validCertificateString = "MIIGrDCCBJSgAwIBAgIEAdTnfTANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJSTzESMBAGA1UEBxMJQnVjaGFyZXN0MRgwFgYDVQQKEw9DeWJlckdob3N0IFMuQS4xGzAZBgNVBAMTEkN5YmVyR2hvc3QgUm9vdCBDQTEhMB8GCSqGSIb3DQEJARYSaW5mb0BjeWJlcmdob3N0LnJvMB4XDTIwMDcwNDE1MjkzNloXDTMwMDcwMjE1MjkzNlowfTELMAkGA1UEBhMCUk8xEjAQBgNVBAcMCUJ1Y2hhcmVzdDEYMBYGA1UECgwPQ3liZXJHaG9zdCBTLkEuMR0wGwYDVQQDDBRjLmoua2xhdmVyQGdtYWlsLmNvbTEhMB8GCSqGSIb3DQEJARYSaW5mb0BjeWJlcmdob3N0LnJvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAobp2NlGUHMNBe08YEOnVG3QJjF3ZaXbRhE/II9rmtgJTNZtDohGChvFlNRsExKzVrKxHCeuJkVffwzQ6fYk4/M1RdYLJUh0UVw3e4WdApw8E7TJZxDYm4SHQNXUvt1Rt5TjslcXxIpDZgrMSc/kHROYEL9tdgdzPZErUJehXyJPhEzIrzmAJh501x7WwKPz9ctSVlItyavqEWFF2vyUa6X9DYmD9mQTz5c+VXNO5DkXmPFBIaEVDnvFtcjGJ56yEvFnWVukL+OUX7ezowrIOFOcp9udjgpeiHq+XvsQ6ER0DJt25MiEId3NjkxtZ8BitDftTcLN/kt81hWKT7adMVc3kpIZ80cxrwRCttMd7sHAzKI9u7pMxv10eUOsIEY87ewBe3l6KvEnjA+9uIjim6gLLebDIaEH50Ee9PzNJ8fqQ2u54Ab4bt00/H1sUnJ6Ss/+WsQDOK1BsPRKKcnHZntOlHrs2Tu5+txKNU2cOapI8SjVULUNKrRXASbpfWnLUfri/HO742bJb/TjkOJcOxta3hTPFAhaRWBusVlB41XVHeuH5DAhugYXeSNK6/6Ul8YvKUNH/7QbxuGIGXfth19Xl4QLI1umyEjZopSlt3tOiO2V1soVNSQCCfxXVoCTMESMLjhkjWdmBDhdy2GTW7S4YoJfqVKiS18rYkN7I4ZMCAwEAAaOCATQwggEwMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMDQGCWCGSAGG+EIBDQQnFiVDeWJlckdob3N0IEdlbmVyYXRlZCBVc2VyIENlcnRpZmljYXRlMBEGCWCGSAGG+EIBAQQEAwIHgDAdBgNVHQ4EFgQULwUtU5s6pL2NN9gPeEnKX0dhwiswga0GA1UdIwSBpTCBooAU6tdK1g/He5qzjeAoM5eHt4in9iWhf6R9MHsxCzAJBgNVBAYTAlJPMRIwEAYDVQQHEwlCdWNoYXJlc3QxGDAWBgNVBAoTD0N5YmVyR2hvc3QgUy5BLjEbMBkGA1UEAxMSQ3liZXJHaG9zdCBSb290IENBMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGN5YmVyZ2hvc3Qucm+CCQCcVButZsQ0uzANBgkqhkiG9w0BAQsFAAOCAgEAystGIMYhQWaEdTqlnLCytrr8657t+PuidZMNNIaPB3wN2Fi2xKf14DTg03mqxjmPPb+f+PVNIOV5PdWD4jcQwOP1GEboGV0DFzlRGeAtDcvKwdee4oASJbZq1CETqDaohQTxKEWC+UBk2F36nOaEI6Sab+Mb4cR9//PAwvzOqrXuGF5NuIOX7eFtCMQSgQq6lRRqTQjekm0Dxigx4JA92Jo2qZRwCJ0T3IXBJGL831HCFJbDWv8PV3lsfFb/i2+vr54uywFQVWWp18dYi97gipfuQ4zRg2Ldx5aXSmnhhKpg5ioZvtk043QofF12YORhobElqavRbvvhZvlCouvcuoq9QKi7IPe5SJZkZ1X7ezMesCwBzwFpt6vRUAcslsNFbcYS1iSENlY/PTcDqBhbKuc9yAhq+/aUgaY/8VF5RWVzSRZufbf3BPwOkE4K0UybaobO/YX0JOkCacAD+4tdR6YSXNIMMRAOCBQvxbxFXaHzhwhzBAjdsC56FrJKwXvQrRLU3tF4P0zFMeNTay8uTtUXugDK7EnklLESuYdpUJ8bUMlAUhJBi6UFI9/icMudxXvLRvhnBW9EtKib5JnVFUovcEUt+3EJbyst05nkL4YPjQS4TC9DHdo5SyRAy1TpiOCYTbretAFZRhh6ycUN5hBeN8GMQxiMreMtDV4PEIQ=" //nolint:lll
|
||||||
|
testCases := map[string]struct {
|
||||||
|
b []byte
|
||||||
|
certificate string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
"no input": {
|
||||||
|
err: fmt.Errorf("cannot decode PEM block from client certificate"),
|
||||||
|
},
|
||||||
|
"bad input": {
|
||||||
|
b: []byte{1, 2, 3},
|
||||||
|
err: fmt.Errorf("cannot decode PEM block from client certificate"),
|
||||||
|
},
|
||||||
|
"valid key": {
|
||||||
|
b: []byte(validPEM),
|
||||||
|
certificate: validCertificateString,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
certificate, err := extractClientCertificate(testCase.b)
|
||||||
|
if testCase.err != nil {
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, testCase.certificate, certificate)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
154
internal/configuration/dns.go
Normal file
154
internal/configuration/dns.go
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
unboundmodels "github.com/qdm12/dns/pkg/models"
|
||||||
|
unbound "github.com/qdm12/dns/pkg/unbound"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DNS contains settings to configure Unbound for DNS over TLS operation.
|
||||||
|
type DNS struct { //nolint:maligned
|
||||||
|
Enabled bool
|
||||||
|
PlaintextAddress net.IP
|
||||||
|
KeepNameserver bool
|
||||||
|
BlockMalicious bool
|
||||||
|
BlockAds bool
|
||||||
|
BlockSurveillance bool
|
||||||
|
UpdatePeriod time.Duration
|
||||||
|
Unbound unboundmodels.Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *DNS) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *DNS) lines() (lines []string) {
|
||||||
|
lines = append(lines, lastIndent+"DNS:")
|
||||||
|
|
||||||
|
if settings.PlaintextAddress != nil {
|
||||||
|
lines = append(lines, indent+lastIndent+"Plaintext address: "+settings.PlaintextAddress.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.KeepNameserver {
|
||||||
|
lines = append(lines, indent+lastIndent+"Keep nameserver (disabled blocking): yes")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !settings.Enabled {
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"DNS over TLS:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+indent+lastIndent+"Unbound:")
|
||||||
|
for _, line := range settings.Unbound.Lines() {
|
||||||
|
lines = append(lines, indent+indent+indent+line)
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.BlockMalicious {
|
||||||
|
lines = append(lines, indent+indent+lastIndent+"Block malicious: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.BlockAds {
|
||||||
|
lines = append(lines, indent+indent+lastIndent+"Block ads: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.BlockSurveillance {
|
||||||
|
lines = append(lines, indent+indent+lastIndent+"Block surveillance: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.UpdatePeriod > 0 {
|
||||||
|
lines = append(lines, indent+indent+lastIndent+"Update: every "+settings.UpdatePeriod.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrUnboundSettings = errors.New("failed getting Unbound settings")
|
||||||
|
ErrDNSProviderNoData = errors.New("DNS provider has no associated data")
|
||||||
|
ErrDNSProviderNoTLS = errors.New("DNS provider does not support DNS over TLS")
|
||||||
|
ErrDNSNoIPv6Support = errors.New("no DNS provider supports IPv6")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *DNS) read(r reader) (err error) {
|
||||||
|
settings.Enabled, err = r.env.OnOff("DOT", params.Default("on"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plain DNS settings
|
||||||
|
if err := settings.readDNSPlaintext(r.env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.KeepNameserver, err = r.env.OnOff("DNS_KEEP_NAMESERVER", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNS over TLS external settings
|
||||||
|
settings.BlockMalicious, err = r.env.OnOff("BLOCK_MALICIOUS", params.Default("on"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.BlockSurveillance, err = r.env.OnOff("BLOCK_SURVEILLANCE", params.Default("on"),
|
||||||
|
params.RetroKeys([]string{"BLOCK_NSA"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.BlockAds, err = r.env.OnOff("BLOCK_ADS", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.UpdatePeriod, err = r.env.Duration("DNS_UPDATE_PERIOD", params.Default("24h"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.readUnbound(r); err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", ErrUnboundSettings, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consistency check
|
||||||
|
IPv6Support := false
|
||||||
|
for _, provider := range settings.Unbound.Providers {
|
||||||
|
providerData, ok := unbound.GetProviderData(provider)
|
||||||
|
switch {
|
||||||
|
case !ok:
|
||||||
|
return fmt.Errorf("%w: %s", ErrDNSProviderNoData, provider)
|
||||||
|
case !providerData.SupportsTLS:
|
||||||
|
return fmt.Errorf("%w: %s", ErrDNSProviderNoTLS, provider)
|
||||||
|
case providerData.SupportsIPv6:
|
||||||
|
IPv6Support = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.Unbound.IPv6 && !IPv6Support {
|
||||||
|
return ErrDNSNoIPv6Support
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrDNSAddressNotAnIP = errors.New("DNS plaintext address is not an IP address")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *DNS) readDNSPlaintext(env params.Env) error {
|
||||||
|
s, err := env.Get("DNS_PLAINTEXT_ADDRESS", params.Default("1.1.1.1"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.PlaintextAddress = net.ParseIP(s)
|
||||||
|
if settings.PlaintextAddress == nil {
|
||||||
|
return fmt.Errorf("%w: %s", ErrDNSAddressNotAnIP, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
73
internal/configuration/dns_test.go
Normal file
73
internal/configuration/dns_test.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/dns/pkg/models"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_DNS_Lines(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
testCases := map[string]struct {
|
||||||
|
settings DNS
|
||||||
|
lines []string
|
||||||
|
}{
|
||||||
|
"disabled DOT": {
|
||||||
|
settings: DNS{
|
||||||
|
PlaintextAddress: net.IP{1, 1, 1, 1},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--DNS:",
|
||||||
|
" |--Plaintext address: 1.1.1.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"enabled DOT": {
|
||||||
|
settings: DNS{
|
||||||
|
Enabled: true,
|
||||||
|
KeepNameserver: true,
|
||||||
|
Unbound: models.Settings{
|
||||||
|
Providers: []string{"cloudflare"},
|
||||||
|
},
|
||||||
|
BlockMalicious: true,
|
||||||
|
BlockAds: true,
|
||||||
|
BlockSurveillance: true,
|
||||||
|
UpdatePeriod: time.Hour,
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--DNS:",
|
||||||
|
" |--Keep nameserver (disabled blocking): yes",
|
||||||
|
" |--DNS over TLS:",
|
||||||
|
" |--Unbound:",
|
||||||
|
" |--DNS over TLS providers:",
|
||||||
|
" |--cloudflare",
|
||||||
|
" |--Listening port: 0",
|
||||||
|
" |--Access control:",
|
||||||
|
" |--Allowed:",
|
||||||
|
" |--Caching: disabled",
|
||||||
|
" |--IPv4 resolution: disabled",
|
||||||
|
" |--IPv6 resolution: disabled",
|
||||||
|
" |--Verbosity level: 0/5",
|
||||||
|
" |--Verbosity details level: 0/4",
|
||||||
|
" |--Validation log level: 0/2",
|
||||||
|
" |--Blocked hostnames:",
|
||||||
|
" |--Blocked IP addresses:",
|
||||||
|
" |--Allowed hostnames:",
|
||||||
|
" |--Block malicious: enabled",
|
||||||
|
" |--Block ads: enabled",
|
||||||
|
" |--Block surveillance: enabled",
|
||||||
|
" |--Update: every 1h0m0s",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
lines := testCase.settings.lines()
|
||||||
|
assert.Equal(t, testCase.lines, lines)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
93
internal/configuration/firewall.go
Normal file
93
internal/configuration/firewall.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Firewall contains settings to customize the firewall operation.
|
||||||
|
type Firewall struct {
|
||||||
|
VPNInputPorts []uint16
|
||||||
|
InputPorts []uint16
|
||||||
|
OutboundSubnets []net.IPNet
|
||||||
|
Enabled bool
|
||||||
|
Debug bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Firewall) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Firewall) lines() (lines []string) {
|
||||||
|
if !settings.Enabled {
|
||||||
|
lines = append(lines, lastIndent+"Firewall: disabled ⚠️")
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Firewall:")
|
||||||
|
|
||||||
|
if settings.Debug {
|
||||||
|
lines = append(lines, indent+lastIndent+"Debug: on")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.VPNInputPorts) > 0 {
|
||||||
|
lines = append(lines, indent+lastIndent+"VPN input ports: "+
|
||||||
|
strings.Join(uint16sToStrings(settings.VPNInputPorts), ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.InputPorts) > 0 {
|
||||||
|
lines = append(lines, indent+lastIndent+"Input ports: "+
|
||||||
|
strings.Join(uint16sToStrings(settings.InputPorts), ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.OutboundSubnets) > 0 {
|
||||||
|
lines = append(lines, indent+lastIndent+"Outbound subnets: "+
|
||||||
|
strings.Join(ipNetsToStrings(settings.OutboundSubnets), ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Firewall) read(r reader) (err error) {
|
||||||
|
settings.Enabled, err = r.env.OnOff("FIREWALL", params.Default("on"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Debug, err = r.env.OnOff("FIREWALL_DEBUG", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.readVPNInputPorts(r.env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.readInputPorts(r.env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.readOutboundSubnets(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Firewall) readVPNInputPorts(env params.Env) (err error) {
|
||||||
|
settings.VPNInputPorts, err = readCSVPorts(env, "FIREWALL_VPN_INPUT_PORTS")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Firewall) readInputPorts(env params.Env) (err error) {
|
||||||
|
settings.VPNInputPorts, err = readCSVPorts(env, "FIREWALL_INPUT_PORTS")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Firewall) readOutboundSubnets(r reader) (err error) {
|
||||||
|
retroOption := params.RetroKeys([]string{"EXTRA_SUBNETS"}, r.onRetroActive)
|
||||||
|
settings.OutboundSubnets, err = readCSVIPNets(r.env, "FIREWALL_OUTBOUND_SUBNETS", retroOption)
|
||||||
|
return err
|
||||||
|
}
|
||||||
105
internal/configuration/httpproxy.go
Normal file
105
internal/configuration/httpproxy.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HTTPProxy contains settings to configure the HTTP proxy.
|
||||||
|
type HTTPProxy struct {
|
||||||
|
User string
|
||||||
|
Password string
|
||||||
|
Port uint16
|
||||||
|
Enabled bool
|
||||||
|
Stealth bool
|
||||||
|
Log bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *HTTPProxy) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *HTTPProxy) lines() (lines []string) {
|
||||||
|
if !settings.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"HTTP proxy:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Port: "+strconv.Itoa(int(settings.Port)))
|
||||||
|
|
||||||
|
if settings.User != "" {
|
||||||
|
lines = append(lines, indent+lastIndent+"Authentication: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.Log {
|
||||||
|
lines = append(lines, indent+lastIndent+"Log: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.Stealth {
|
||||||
|
lines = append(lines, indent+lastIndent+"Stealth: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *HTTPProxy) read(r reader) (err error) {
|
||||||
|
settings.Enabled, err = r.env.OnOff("HTTPPROXY", params.Default("off"),
|
||||||
|
params.RetroKeys([]string{"TINYPROXY", "PROXY"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.User, err = r.getFromEnvOrSecretFile("HTTPPROXY_USER", false, // compulsory
|
||||||
|
[]string{"TINYPROXY_USER", "PROXY_USER"})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Password, err = r.getFromEnvOrSecretFile("HTTPPROXY_USER", false,
|
||||||
|
[]string{"TINYPROXY_PASSWORD", "PROXY_PASSWORD"})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Stealth, err = r.env.OnOff("HTTPPROXY_STEALTH", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.readLog(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var warning string
|
||||||
|
settings.Port, warning, err = r.env.ListeningPort("HTTPPROXY_PORT", params.Default("8888"),
|
||||||
|
params.RetroKeys([]string{"TINYPROXY_PORT", "PROXY_PORT"}, r.onRetroActive))
|
||||||
|
if len(warning) > 0 {
|
||||||
|
r.logger.Warn(warning)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *HTTPProxy) readLog(r reader) error {
|
||||||
|
s, err := r.env.Get("HTTPPROXY_LOG",
|
||||||
|
params.RetroKeys([]string{"PROXY_LOG_LEVEL", "TINYPROXY_LOG"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch strings.ToLower(s) {
|
||||||
|
case "on":
|
||||||
|
settings.Enabled = true
|
||||||
|
// Retro compatibility
|
||||||
|
case "info", "connect", "notice":
|
||||||
|
settings.Enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
22
internal/configuration/lines.go
Normal file
22
internal/configuration/lines.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func uint16sToStrings(uint16s []uint16) (strings []string) {
|
||||||
|
strings = make([]string, len(uint16s))
|
||||||
|
for i := range uint16s {
|
||||||
|
strings[i] = strconv.Itoa(int(uint16s[i]))
|
||||||
|
}
|
||||||
|
return strings
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipNetsToStrings(ipNets []net.IPNet) (strings []string) {
|
||||||
|
strings = make([]string, len(ipNets))
|
||||||
|
for i := range ipNets {
|
||||||
|
strings[i] = ipNets[i].String()
|
||||||
|
}
|
||||||
|
return strings
|
||||||
|
}
|
||||||
79
internal/configuration/mullvad.go
Normal file
79
internal/configuration/mullvad.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) mullvadLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Countries) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Countries: "+commaJoin(settings.ServerSelection.Countries))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.Cities) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Cities: "+commaJoin(settings.ServerSelection.Cities))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.ISPs) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"ISPs: "+commaJoin(settings.ServerSelection.ISPs))
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.ServerSelection.CustomPort > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Custom port: "+strconv.Itoa(int(settings.ServerSelection.CustomPort)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.ExtraConfigOptions.OpenVPNIPv6 {
|
||||||
|
lines = append(lines, lastIndent+"IPv6: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readMullvad(r reader) (err error) {
|
||||||
|
settings.Name = constants.Mullvad
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Countries, err = r.env.CSVInside("COUNTRY", constants.MullvadCountryChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Cities, err = r.env.CSVInside("CITY", constants.MullvadCityChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.ISPs, err = r.env.CSVInside("ISP", constants.MullvadISPChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.CustomPort, err = readCustomPort(r.env, settings.ServerSelection.Protocol,
|
||||||
|
[]uint16{80, 443, 1401}, []uint16{53, 1194, 1195, 1196, 1197, 1300, 1301, 1302, 1303, 1400})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Owned, err = r.env.YesNo("OWNED", params.Default("no"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ExtraConfigOptions.OpenVPNIPv6, err = r.env.OnOff("OPENVPN_IPV6", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
72
internal/configuration/nordvpn.go
Normal file
72
internal/configuration/nordvpn.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) nordvpnLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
if numbersUint16 := settings.ServerSelection.Numbers; len(numbersUint16) > 0 {
|
||||||
|
numbersString := make([]string, len(numbersUint16))
|
||||||
|
for i, numberUint16 := range numbersUint16 {
|
||||||
|
numbersString[i] = strconv.Itoa(int(numberUint16))
|
||||||
|
}
|
||||||
|
lines = append(lines, lastIndent+"Numbers: "+commaJoin(numbersString))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readNordvpn(r reader) (err error) {
|
||||||
|
settings.Name = constants.Nordvpn
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.NordvpnRegionChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Numbers, err = readNordVPNServerNumbers(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readNordVPNServerNumbers(env params.Env) (numbers []uint16, err error) {
|
||||||
|
possibilities := make([]string, 65537)
|
||||||
|
for i := range possibilities {
|
||||||
|
possibilities[i] = fmt.Sprintf("%d", i)
|
||||||
|
}
|
||||||
|
possibilities[65536] = ""
|
||||||
|
values, err := env.CSVInside("SERVER_NUMBER", possibilities)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
numbers = make([]uint16, len(values))
|
||||||
|
for i := range values {
|
||||||
|
n, err := strconv.Atoi(values[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
numbers[i] = uint16(n)
|
||||||
|
}
|
||||||
|
return numbers, nil
|
||||||
|
}
|
||||||
138
internal/configuration/openvpn.go
Normal file
138
internal/configuration/openvpn.go
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OpenVPN contains settings to configure the OpenVPN client.
|
||||||
|
type OpenVPN struct {
|
||||||
|
User string `json:"user"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Verbosity int `json:"verbosity"`
|
||||||
|
MSSFix uint16 `json:"mssfix"`
|
||||||
|
Root bool `json:"run_as_root"`
|
||||||
|
Cipher string `json:"cipher"`
|
||||||
|
Auth string `json:"auth"`
|
||||||
|
Provider Provider `json:"provider"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *OpenVPN) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *OpenVPN) lines() (lines []string) {
|
||||||
|
lines = append(lines, lastIndent+"OpenVPN:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Verbosity level: "+strconv.Itoa(settings.Verbosity))
|
||||||
|
|
||||||
|
if settings.Root {
|
||||||
|
lines = append(lines, indent+lastIndent+"Run as root: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.Cipher) > 0 {
|
||||||
|
lines = append(lines, indent+lastIndent+"Custom cipher: "+settings.Cipher)
|
||||||
|
}
|
||||||
|
if len(settings.Auth) > 0 {
|
||||||
|
lines = append(lines, indent+lastIndent+"Custom auth algorithm: "+settings.Auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Provider:")
|
||||||
|
for _, line := range settings.Provider.lines() {
|
||||||
|
lines = append(lines, indent+indent+line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidVPNProvider = errors.New("invalid VPN provider")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *OpenVPN) read(r reader) (err error) {
|
||||||
|
vpnsp, err := r.env.Inside("VPNSP", []string{
|
||||||
|
"pia", "private internet access", "mullvad", "windscribe", "surfshark",
|
||||||
|
"cyberghost", "vyprvpn", "nordvpn", "purevpn", "privado"},
|
||||||
|
params.Default("private internet access"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if vpnsp == "pia" { // retro compatibility
|
||||||
|
vpnsp = "private internet access"
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Provider.Name = vpnsp
|
||||||
|
|
||||||
|
settings.User, err = r.getFromEnvOrSecretFile("OPENVPN_USER", true, []string{"USER"})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Remove spaces in user ID to simplify user's life, thanks @JeordyR
|
||||||
|
settings.User = strings.ReplaceAll(settings.User, " ", "")
|
||||||
|
|
||||||
|
if settings.Provider.Name == constants.Mullvad {
|
||||||
|
settings.Password = "m"
|
||||||
|
} else {
|
||||||
|
settings.Password, err = r.getFromEnvOrSecretFile("OPENVPN_PASSWORD", true, []string{"PASSWORD"})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Verbosity, err = r.env.IntRange("OPENVPN_VERBOSITY", 0, 6, params.Default("1"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Root, err = r.env.YesNo("OPENVPN_ROOT", params.Default("yes"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Cipher, err = r.env.Get("OPENVPN_CIPHER")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Auth, err = r.env.Get("OPENVPN_AUTH")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mssFix, err := r.env.IntRange("OPENVPN_MSSFIX", 0, 10000, params.Default("0"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.MSSFix = uint16(mssFix)
|
||||||
|
|
||||||
|
var readProvider func(r reader) error
|
||||||
|
switch settings.Provider.Name {
|
||||||
|
case constants.PrivateInternetAccess:
|
||||||
|
readProvider = settings.Provider.readPrivateInternetAccess
|
||||||
|
case constants.Mullvad:
|
||||||
|
readProvider = settings.Provider.readMullvad
|
||||||
|
case constants.Windscribe:
|
||||||
|
readProvider = settings.Provider.readWindscribe
|
||||||
|
case constants.Surfshark:
|
||||||
|
readProvider = settings.Provider.readSurfshark
|
||||||
|
case constants.Cyberghost:
|
||||||
|
readProvider = settings.Provider.readCyberghost
|
||||||
|
case constants.Vyprvpn:
|
||||||
|
readProvider = settings.Provider.readVyprvpn
|
||||||
|
case constants.Nordvpn:
|
||||||
|
readProvider = settings.Provider.readNordvpn
|
||||||
|
case constants.Purevpn:
|
||||||
|
readProvider = settings.Provider.readPurevpn
|
||||||
|
case constants.Privado:
|
||||||
|
readProvider = settings.Provider.readPrivado
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%w: %s", ErrInvalidVPNProvider, settings.Provider.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return readProvider(r)
|
||||||
|
}
|
||||||
27
internal/configuration/openvpn_test.go
Normal file
27
internal/configuration/openvpn_test.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_OpenVPN_JSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
in := OpenVPN{
|
||||||
|
Root: true,
|
||||||
|
Provider: Provider{
|
||||||
|
Name: "name",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
data, err := json.Marshal(in)
|
||||||
|
require.NoError(t, err)
|
||||||
|
//nolint:lll
|
||||||
|
assert.Equal(t, `{"user":"","password":"","verbosity":0,"mssfix":0,"run_as_root":true,"cipher":"","auth":"","provider":{"name":"name","server_selection":{"network_protocol":"","regions":null,"group":"","countries":null,"cities":null,"hostnames":null,"isps":null,"owned":false,"custom_port":0,"numbers":null,"encryption_preset":""},"extra_config":{"encryption_preset":"","openvpn_ipv6":false},"port_forwarding":{"enabled":false,"filepath":""}}}`, string(data))
|
||||||
|
var out OpenVPN
|
||||||
|
err = json.Unmarshal(data, &out)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, in, out)
|
||||||
|
}
|
||||||
36
internal/configuration/privado.go
Normal file
36
internal/configuration/privado.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) privadoLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Hostnames) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Hostnames: "+commaJoin(settings.ServerSelection.Hostnames))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readPrivado(r reader) (err error) {
|
||||||
|
settings.Name = constants.Privado
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME",
|
||||||
|
constants.PrivadoHostnameChoices(), params.RetroKeys([]string{"HOSTNAME"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
77
internal/configuration/privateinternetaccess.go
Normal file
77
internal/configuration/privateinternetaccess.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) privateinternetaccessLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Encryption preset: "+settings.ServerSelection.EncryptionPreset)
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Custom port: "+strconv.Itoa(int(settings.ServerSelection.CustomPort)))
|
||||||
|
|
||||||
|
if settings.PortForwarding.Enabled {
|
||||||
|
lines = append(lines, lastIndent+"Port forwarding:")
|
||||||
|
for _, line := range settings.PortForwarding.lines() {
|
||||||
|
lines = append(lines, indent+line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readPrivateInternetAccess(r reader) (err error) {
|
||||||
|
settings.Name = constants.PrivateInternetAccess
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptionPreset, err := r.env.Inside("PIA_ENCRYPTION",
|
||||||
|
[]string{constants.PIAEncryptionPresetNormal, constants.PIAEncryptionPresetStrong},
|
||||||
|
params.RetroKeys([]string{"ENCRYPTION"}, r.onRetroActive),
|
||||||
|
params.Default(constants.PIACertificateStrong),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.ServerSelection.EncryptionPreset = encryptionPreset
|
||||||
|
settings.ExtraConfigOptions.EncryptionPreset = encryptionPreset
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.PIAGeoChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.CustomPort, err = readPortOrZero(r.env, "PORT")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.PortForwarding.Enabled, err = r.env.OnOff("PORT_FORWARDING", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if settings.PortForwarding.Enabled {
|
||||||
|
settings.PortForwarding.Filepath, err = r.env.Path("PORT_FORWARDING_STATUS_FILE",
|
||||||
|
params.Default("/tmp/gluetun/forwarded_port"), params.CaseSensitiveValue())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
105
internal/configuration/provider.go
Normal file
105
internal/configuration/provider.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider contains settings specific to a VPN provider.
|
||||||
|
type Provider struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ServerSelection ServerSelection `json:"server_selection"`
|
||||||
|
ExtraConfigOptions ExtraConfigOptions `json:"extra_config"`
|
||||||
|
PortForwarding PortForwarding `json:"port_forwarding"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) lines() (lines []string) {
|
||||||
|
lines = append(lines, lastIndent+strings.Title(settings.Name)+" settings:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Network protocol: "+settings.ServerSelection.Protocol)
|
||||||
|
|
||||||
|
if settings.ServerSelection.TargetIP != nil {
|
||||||
|
lines = append(lines, indent+lastIndent+"Target IP address: "+settings.ServerSelection.TargetIP.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var providerLines []string
|
||||||
|
switch strings.ToLower(settings.Name) {
|
||||||
|
case "cyberghost":
|
||||||
|
providerLines = settings.cyberghostLines()
|
||||||
|
case "mullvad":
|
||||||
|
providerLines = settings.mullvadLines()
|
||||||
|
case "nordvpn":
|
||||||
|
providerLines = settings.nordvpnLines()
|
||||||
|
case "privado":
|
||||||
|
providerLines = settings.privadoLines()
|
||||||
|
case "private internet access":
|
||||||
|
providerLines = settings.privateinternetaccessLines()
|
||||||
|
case "purevpn":
|
||||||
|
providerLines = settings.purevpnLines()
|
||||||
|
case "surfshark":
|
||||||
|
providerLines = settings.surfsharkLines()
|
||||||
|
case "vyprvpn":
|
||||||
|
providerLines = settings.vyprvpnLines()
|
||||||
|
case "windscribe":
|
||||||
|
providerLines = settings.windscribeLines()
|
||||||
|
default:
|
||||||
|
panic(`Missing lines method for provider "` +
|
||||||
|
settings.Name + `"! Please create a Github issue.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range providerLines {
|
||||||
|
lines = append(lines, indent+line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaJoin(slice []string) string {
|
||||||
|
return strings.Join(slice, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func readProtocol(env params.Env) (protocol string, err error) {
|
||||||
|
return env.Inside("PROTOCOL", []string{constants.TCP, constants.UDP}, params.Default(constants.UDP))
|
||||||
|
}
|
||||||
|
|
||||||
|
func readTargetIP(env params.Env) (targetIP net.IP, err error) {
|
||||||
|
return readIP(env, "OPENVPN_TARGET_IP")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidProtocol = errors.New("invalid network protocol")
|
||||||
|
)
|
||||||
|
|
||||||
|
func readCustomPort(env params.Env, protocol string,
|
||||||
|
allowedTCP, allowedUDP []uint16) (port uint16, err error) {
|
||||||
|
port, err = readPortOrZero(env, "PORT")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if port == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch protocol {
|
||||||
|
case constants.TCP:
|
||||||
|
for i := range allowedTCP {
|
||||||
|
if allowedTCP[i] == port {
|
||||||
|
return port, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("%w: port %d for TCP protocol", ErrInvalidPort, port)
|
||||||
|
case constants.UDP:
|
||||||
|
for i := range allowedUDP {
|
||||||
|
if allowedUDP[i] == port {
|
||||||
|
return port, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("%w: port %d for UDP protocol", ErrInvalidPort, port)
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("%w: %s", ErrInvalidProtocol, protocol)
|
||||||
|
}
|
||||||
|
}
|
||||||
245
internal/configuration/provider_test.go
Normal file
245
internal/configuration/provider_test.go
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/params/mock_params"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errDummy = errors.New("dummy")
|
||||||
|
|
||||||
|
func Test_Provider_lines(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := map[string]struct {
|
||||||
|
settings Provider
|
||||||
|
lines []string
|
||||||
|
}{
|
||||||
|
"cyberghost": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Cyberghost,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Group: "group",
|
||||||
|
Regions: []string{"a", "El country"},
|
||||||
|
},
|
||||||
|
ExtraConfigOptions: ExtraConfigOptions{
|
||||||
|
ClientKey: "a",
|
||||||
|
ClientCertificate: "a",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Cyberghost settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Server group: group",
|
||||||
|
" |--Regions: a, El country",
|
||||||
|
" |--Client key is set",
|
||||||
|
" |--Client certificate is set",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"mullvad": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Mullvad,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Countries: []string{"a", "b"},
|
||||||
|
Cities: []string{"c", "d"},
|
||||||
|
ISPs: []string{"e", "f"},
|
||||||
|
CustomPort: 1,
|
||||||
|
},
|
||||||
|
ExtraConfigOptions: ExtraConfigOptions{
|
||||||
|
OpenVPNIPv6: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Mullvad settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Countries: a, b",
|
||||||
|
" |--Cities: c, d",
|
||||||
|
" |--ISPs: e, f",
|
||||||
|
" |--Custom port: 1",
|
||||||
|
" |--IPv6: enabled",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"nordvpn": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Nordvpn,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Regions: []string{"a", "b"},
|
||||||
|
Numbers: []uint16{1, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Nordvpn settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Regions: a, b",
|
||||||
|
" |--Numbers: 1, 2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"privado": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Privado,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Hostnames: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Privado settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Hostnames: a, b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"private internet access": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.PrivateInternetAccess,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Regions: []string{"a", "b"},
|
||||||
|
EncryptionPreset: constants.PIAEncryptionPresetStrong,
|
||||||
|
CustomPort: 1,
|
||||||
|
},
|
||||||
|
PortForwarding: PortForwarding{
|
||||||
|
Enabled: true,
|
||||||
|
Filepath: string("/here"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Private Internet Access settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Regions: a, b",
|
||||||
|
" |--Encryption preset: strong",
|
||||||
|
" |--Custom port: 1",
|
||||||
|
" |--Port forwarding:",
|
||||||
|
" |--File path: /here",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"purevpn": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Purevpn,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Regions: []string{"a", "b"},
|
||||||
|
Countries: []string{"c", "d"},
|
||||||
|
Cities: []string{"e", "f"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Purevpn settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Regions: a, b",
|
||||||
|
" |--Countries: c, d",
|
||||||
|
" |--Cities: e, f",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"surfshark": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Surfshark,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Regions: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Surfshark settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Regions: a, b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"vyprvpn": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Vyprvpn,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Regions: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Vyprvpn settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Regions: a, b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"windscribe": {
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Windscribe,
|
||||||
|
ServerSelection: ServerSelection{
|
||||||
|
Protocol: constants.UDP,
|
||||||
|
Regions: []string{"a", "b"},
|
||||||
|
Cities: []string{"c", "d"},
|
||||||
|
Hostnames: []string{"e", "f"},
|
||||||
|
CustomPort: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"|--Windscribe settings:",
|
||||||
|
" |--Network protocol: udp",
|
||||||
|
" |--Regions: a, b",
|
||||||
|
" |--Cities: c, d",
|
||||||
|
" |--Hostnames: e, f",
|
||||||
|
" |--Custom port: 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
lines := testCase.settings.lines()
|
||||||
|
|
||||||
|
assert.Equal(t, testCase.lines, lines)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_readProtocol(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := map[string]struct {
|
||||||
|
mockStr string
|
||||||
|
mockErr error
|
||||||
|
protocol string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
"error": {
|
||||||
|
mockErr: errDummy,
|
||||||
|
err: errDummy,
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
mockStr: "tcp",
|
||||||
|
protocol: constants.TCP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
|
||||||
|
env := mock_params.NewMockEnv(ctrl)
|
||||||
|
env.EXPECT().
|
||||||
|
Inside("PROTOCOL", []string{"tcp", "udp"}, gomock.Any()).
|
||||||
|
Return(testCase.mockStr, testCase.mockErr)
|
||||||
|
|
||||||
|
protocol, err := readProtocol(env)
|
||||||
|
|
||||||
|
if testCase.err != nil {
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, testCase.protocol, protocol)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
46
internal/configuration/publicip.go
Normal file
46
internal/configuration/publicip.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublicIP struct {
|
||||||
|
Period time.Duration `json:"period"`
|
||||||
|
IPFilepath string `json:"ip_filepath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *PublicIP) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *PublicIP) lines() (lines []string) {
|
||||||
|
if settings.Period == 0 {
|
||||||
|
lines = append(lines, lastIndent+"Public IP getter: disabled")
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Public IP getter:")
|
||||||
|
lines = append(lines, indent+lastIndent+"Fetch period: "+settings.Period.String())
|
||||||
|
lines = append(lines, indent+lastIndent+"IP file: "+settings.IPFilepath)
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *PublicIP) read(r reader) (err error) {
|
||||||
|
settings.Period, err = r.env.Duration("PUBLICIP_PERIOD", params.Default("12h"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.IPFilepath, err = r.env.Path("PUBLICIP_FILE", params.CaseSensitiveValue(),
|
||||||
|
params.Default("/tmp/gluetun/ip"),
|
||||||
|
params.RetroKeys([]string{"IP_STATUS_FILE"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
52
internal/configuration/purevpn.go
Normal file
52
internal/configuration/purevpn.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) purevpnLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.Countries) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Countries: "+commaJoin(settings.ServerSelection.Countries))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.Cities) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Cities: "+commaJoin(settings.ServerSelection.Cities))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readPurevpn(r reader) (err error) {
|
||||||
|
settings.Name = constants.Purevpn
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.PurevpnRegionChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Countries, err = r.env.CSVInside("COUNTRY", constants.PurevpnCountryChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Cities, err = r.env.CSVInside("CITY", constants.PurevpnCityChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
129
internal/configuration/reader.go
Normal file
129
internal/configuration/reader.go
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
"github.com/qdm12/golibs/verification"
|
||||||
|
)
|
||||||
|
|
||||||
|
type reader struct {
|
||||||
|
env params.Env
|
||||||
|
logger logging.Logger
|
||||||
|
regex verification.Regex
|
||||||
|
os os.OS
|
||||||
|
}
|
||||||
|
|
||||||
|
func newReader(env params.Env, os os.OS, logger logging.Logger) reader {
|
||||||
|
return reader{
|
||||||
|
env: env,
|
||||||
|
logger: logger,
|
||||||
|
regex: verification.NewRegex(),
|
||||||
|
os: os,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) onRetroActive(oldKey, newKey string) {
|
||||||
|
r.logger.Warn(
|
||||||
|
"You are using the old environment variable %s, please consider changing it to %s",
|
||||||
|
oldKey, newKey,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidPort = errors.New("invalid port")
|
||||||
|
)
|
||||||
|
|
||||||
|
func readCSVPorts(env params.Env, key string) (ports []uint16, err error) {
|
||||||
|
s, err := env.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(s) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
portsStr := strings.Split(s, ",")
|
||||||
|
ports = make([]uint16, len(portsStr))
|
||||||
|
for i, portStr := range portsStr {
|
||||||
|
portInt, err := strconv.Atoi(portStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%w: %q from environment variable %s: %s",
|
||||||
|
ErrInvalidPort, portStr, key, err)
|
||||||
|
} else if portInt <= 0 || portInt > 65535 {
|
||||||
|
return nil, fmt.Errorf("%w: %d from environment variable %s: must be between 1 and 65535",
|
||||||
|
ErrInvalidPort, portInt, key)
|
||||||
|
}
|
||||||
|
ports[i] = uint16(portInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ports, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidIPNet = errors.New("invalid IP network")
|
||||||
|
)
|
||||||
|
|
||||||
|
func readCSVIPNets(env params.Env, key string, options ...params.OptionSetter) (
|
||||||
|
ipNets []net.IPNet, err error) {
|
||||||
|
s, err := env.Get(key, options...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if s == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ipNetsStr := strings.Split(s, ",")
|
||||||
|
ipNets = make([]net.IPNet, len(ipNetsStr))
|
||||||
|
for i, ipNetStr := range ipNetsStr {
|
||||||
|
_, ipNet, err := net.ParseCIDR(ipNetStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%w: %q from environment variable %s: %s",
|
||||||
|
ErrInvalidIPNet, ipNetStr, key, err)
|
||||||
|
} else if ipNet == nil {
|
||||||
|
return nil, fmt.Errorf("%w: %q from environment variable %s: subnet is nil",
|
||||||
|
ErrInvalidIPNet, ipNetStr, key)
|
||||||
|
}
|
||||||
|
ipNets[i] = *ipNet
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipNets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidIP = errors.New("invalid IP address")
|
||||||
|
)
|
||||||
|
|
||||||
|
func readIP(env params.Env, key string) (ip net.IP, err error) {
|
||||||
|
s, err := env.Get(key)
|
||||||
|
if len(s) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = net.ParseIP(s)
|
||||||
|
if ip == nil {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrInvalidIP, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readPortOrZero(env params.Env, key string) (port uint16, err error) {
|
||||||
|
s, err := env.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s) == 0 || s == "0" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return env.Port(key)
|
||||||
|
}
|
||||||
109
internal/configuration/secrets.go
Normal file
109
internal/configuration/secrets.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrGetSecretFilepath = errors.New("cannot get secret file path from env")
|
||||||
|
ErrReadSecretFile = errors.New("cannot read secret file")
|
||||||
|
ErrSecretFileIsEmpty = errors.New("secret file is empty")
|
||||||
|
ErrReadNonSecretFile = errors.New("cannot read non secret file")
|
||||||
|
ErrFilesDoNotExist = errors.New("files do not exist")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *reader) getFromEnvOrSecretFile(envKey string, compulsory bool, retroKeys []string) (value string, err error) {
|
||||||
|
envOptions := []params.OptionSetter{
|
||||||
|
params.Compulsory(), // to fallback on file reading
|
||||||
|
params.CaseSensitiveValue(),
|
||||||
|
params.Unset(),
|
||||||
|
params.RetroKeys(retroKeys, r.onRetroActive),
|
||||||
|
}
|
||||||
|
value, envErr := r.env.Get(envKey, envOptions...)
|
||||||
|
if envErr == nil {
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultSecretFile := "/run/secrets/" + strings.ToLower(envKey)
|
||||||
|
filepath, err := r.env.Get(envKey+"_SECRETFILE",
|
||||||
|
params.CaseSensitiveValue(),
|
||||||
|
params.Default(defaultSecretFile),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("%w: %s", ErrGetSecretFilepath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
file, fileErr := r.os.OpenFile(filepath, os.O_RDONLY, 0)
|
||||||
|
if os.IsNotExist(fileErr) {
|
||||||
|
if compulsory {
|
||||||
|
return "", envErr
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
} else if fileErr != nil {
|
||||||
|
return "", fmt.Errorf("%w: %s", ErrReadSecretFile, fileErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("%w: %s", ErrReadSecretFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
value = string(b)
|
||||||
|
value = strings.TrimSuffix(value, "\n")
|
||||||
|
if compulsory && len(value) == 0 {
|
||||||
|
return "", ErrSecretFileIsEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tries to read from the secret file then the non secret file.
|
||||||
|
func (r *reader) getFromFileOrSecretFile(secretName, filepath string) (
|
||||||
|
b []byte, err error) {
|
||||||
|
defaultSecretFile := "/run/secrets/" + strings.ToLower(secretName)
|
||||||
|
secretFilepath, err := r.env.Get(strings.ToUpper(secretName)+"_SECRETFILE",
|
||||||
|
params.CaseSensitiveValue(),
|
||||||
|
params.Default(defaultSecretFile),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return b, fmt.Errorf("%w: %s", ErrGetSecretFilepath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err = readFromFile(r.os.OpenFile, secretFilepath)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return b, fmt.Errorf("%w: %s", ErrReadSecretFile, err)
|
||||||
|
} else if err == nil {
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secret file does not exist, try the non secret file
|
||||||
|
b, err = readFromFile(r.os.OpenFile, filepath)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrReadSecretFile, err)
|
||||||
|
} else if err == nil {
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("%w: %s and %s", ErrFilesDoNotExist, secretFilepath, filepath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readFromFile(openFile os.OpenFileFunc, filepath string) (b []byte, err error) {
|
||||||
|
file, err := openFile(filepath, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b, err = ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
_ = file.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := file.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
53
internal/configuration/selection.go
Normal file
53
internal/configuration/selection.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerSelection struct {
|
||||||
|
// Common
|
||||||
|
Protocol string `json:"network_protocol"`
|
||||||
|
TargetIP net.IP `json:"target_ip,omitempty"`
|
||||||
|
|
||||||
|
// Cyberghost, PIA, Surfshark, Windscribe, Vyprvpn, NordVPN
|
||||||
|
Regions []string `json:"regions"`
|
||||||
|
|
||||||
|
// Cyberghost
|
||||||
|
Group string `json:"group"`
|
||||||
|
|
||||||
|
Countries []string `json:"countries"` // Mullvad, PureVPN
|
||||||
|
Cities []string `json:"cities"` // Mullvad, PureVPN, Windscribe
|
||||||
|
Hostnames []string `json:"hostnames"` // Windscribe, Privado
|
||||||
|
|
||||||
|
// Mullvad
|
||||||
|
ISPs []string `json:"isps"`
|
||||||
|
Owned bool `json:"owned"`
|
||||||
|
|
||||||
|
// Mullvad, Windscribe, PIA
|
||||||
|
CustomPort uint16 `json:"custom_port"`
|
||||||
|
|
||||||
|
// NordVPN
|
||||||
|
Numbers []uint16 `json:"numbers"`
|
||||||
|
|
||||||
|
// PIA
|
||||||
|
EncryptionPreset string `json:"encryption_preset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtraConfigOptions struct {
|
||||||
|
ClientCertificate string `json:"-"` // Cyberghost
|
||||||
|
ClientKey string `json:"-"` // Cyberghost
|
||||||
|
EncryptionPreset string `json:"encryption_preset"` // PIA
|
||||||
|
OpenVPNIPv6 bool `json:"openvpn_ipv6"` // Mullvad
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortForwarding contains settings for port forwarding.
|
||||||
|
type PortForwarding struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Filepath string `json:"filepath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PortForwarding) lines() (lines []string) {
|
||||||
|
return []string{
|
||||||
|
lastIndent + "File path: " + p.Filepath,
|
||||||
|
}
|
||||||
|
}
|
||||||
49
internal/configuration/server.go
Normal file
49
internal/configuration/server.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ControlServer contains settings to customize the control server operation.
|
||||||
|
type ControlServer struct {
|
||||||
|
Port uint16
|
||||||
|
Log bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *ControlServer) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *ControlServer) lines() (lines []string) {
|
||||||
|
lines = append(lines, lastIndent+"HTTP control server:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Listening port: "+strconv.Itoa(int(settings.Port)))
|
||||||
|
|
||||||
|
if settings.Log {
|
||||||
|
lines = append(lines, indent+lastIndent+"Logging: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *ControlServer) read(r reader) (err error) {
|
||||||
|
settings.Log, err = r.env.OnOff("HTTP_CONTROL_SERVER_LOG", params.Default("on"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var warning string
|
||||||
|
settings.Port, warning, err = r.env.ListeningPort(
|
||||||
|
"HTTP_CONTROL_SERVER_PORT", params.Default("8000"))
|
||||||
|
if len(warning) > 0 {
|
||||||
|
r.logger.Warn(warning)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
97
internal/configuration/settings.go
Normal file
97
internal/configuration/settings.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
"github.com/qdm12/golibs/os"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Settings contains all settings for the program to run.
|
||||||
|
type Settings struct {
|
||||||
|
OpenVPN OpenVPN
|
||||||
|
System System
|
||||||
|
DNS DNS
|
||||||
|
Firewall Firewall
|
||||||
|
HTTPProxy HTTPProxy
|
||||||
|
ShadowSocks ShadowSocks
|
||||||
|
Updater Updater
|
||||||
|
PublicIP PublicIP
|
||||||
|
VersionInformation bool
|
||||||
|
ControlServer ControlServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Settings) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Settings) lines() (lines []string) {
|
||||||
|
lines = append(lines, "Settings summary below:")
|
||||||
|
lines = append(lines, settings.OpenVPN.lines()...)
|
||||||
|
lines = append(lines, settings.DNS.lines()...)
|
||||||
|
lines = append(lines, settings.Firewall.lines()...)
|
||||||
|
lines = append(lines, settings.System.lines()...)
|
||||||
|
lines = append(lines, settings.HTTPProxy.lines()...)
|
||||||
|
lines = append(lines, settings.ShadowSocks.lines()...)
|
||||||
|
lines = append(lines, settings.ControlServer.lines()...)
|
||||||
|
lines = append(lines, settings.Updater.lines()...)
|
||||||
|
lines = append(lines, settings.PublicIP.lines()...)
|
||||||
|
if settings.VersionInformation {
|
||||||
|
lines = append(lines, lastIndent+"Github version information: enabled")
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read obtains all configuration options for the program and returns an error as soon
|
||||||
|
// as an error is encountered reading them.
|
||||||
|
func (settings *Settings) Read(env params.Env, os os.OS, logger logging.Logger) (err error) {
|
||||||
|
r := newReader(env, os, logger)
|
||||||
|
|
||||||
|
settings.VersionInformation, err = r.env.OnOff("VERSION_INFORMATION", params.Default("on"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.OpenVPN.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.System.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.DNS.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.Firewall.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.HTTPProxy.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.ShadowSocks.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.ControlServer.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.Updater.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip := settings.DNS.PlaintextAddress; ip != nil {
|
||||||
|
settings.Updater.DNSAddress = ip.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.PublicIP.read(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
55
internal/configuration/settings_test.go
Normal file
55
internal/configuration/settings_test.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Settings_lines(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := map[string]struct {
|
||||||
|
settings Settings
|
||||||
|
lines []string
|
||||||
|
}{
|
||||||
|
"default settings": {
|
||||||
|
settings: Settings{
|
||||||
|
OpenVPN: OpenVPN{
|
||||||
|
Provider: Provider{
|
||||||
|
Name: constants.Mullvad,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lines: []string{
|
||||||
|
"Settings summary below:",
|
||||||
|
"|--OpenVPN:",
|
||||||
|
" |--Verbosity level: 0",
|
||||||
|
" |--Provider:",
|
||||||
|
" |--Mullvad settings:",
|
||||||
|
" |--Network protocol: ",
|
||||||
|
"|--DNS:",
|
||||||
|
"|--Firewall: disabled ⚠️",
|
||||||
|
"|--System:",
|
||||||
|
" |--Process user ID: 0",
|
||||||
|
" |--Process group ID: 0",
|
||||||
|
" |--Timezone: NOT SET ⚠️ - it can cause time related issues",
|
||||||
|
"|--HTTP control server:",
|
||||||
|
" |--Listening port: 0",
|
||||||
|
"|--Public IP getter: disabled",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
lines := testCase.settings.lines()
|
||||||
|
|
||||||
|
assert.Equal(t, testCase.lines, lines)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
72
internal/configuration/shadowsocks.go
Normal file
72
internal/configuration/shadowsocks.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ShadowSocks contains settings to configure the Shadowsocks server.
|
||||||
|
type ShadowSocks struct {
|
||||||
|
Method string
|
||||||
|
Password string
|
||||||
|
Port uint16
|
||||||
|
Enabled bool
|
||||||
|
Log bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *ShadowSocks) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *ShadowSocks) lines() (lines []string) {
|
||||||
|
if !settings.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Shadowsocks server:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Listening port: "+strconv.Itoa(int(settings.Port)))
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Method: "+settings.Method)
|
||||||
|
|
||||||
|
if settings.Log {
|
||||||
|
lines = append(lines, indent+lastIndent+"Logging: enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *ShadowSocks) read(r reader) (err error) {
|
||||||
|
settings.Enabled, err = r.env.OnOff("SHADOWSOCKS", params.Default("off"))
|
||||||
|
if err != nil || !settings.Enabled {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Password, err = r.getFromEnvOrSecretFile("SHADOWSOCKS_PASSWORD", false, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Log, err = r.env.OnOff("SHADOWSOCKS_LOG", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Method, err = r.env.Get("SHADOWSOCKS_METHOD", params.Default("chacha20-ietf-poly1305"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var warning string
|
||||||
|
settings.Port, warning, err = r.env.ListeningPort("SHADOWSOCKS_PORT", params.Default("8388"))
|
||||||
|
if len(warning) > 0 {
|
||||||
|
r.logger.Warn(warning)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
34
internal/configuration/surfshark.go
Normal file
34
internal/configuration/surfshark.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) surfsharkLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readSurfshark(r reader) (err error) {
|
||||||
|
settings.Name = constants.Surfshark
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.SurfsharkRegionChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
53
internal/configuration/system.go
Normal file
53
internal/configuration/system.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// System contains settings to configure system related elements.
|
||||||
|
type System struct {
|
||||||
|
PUID int
|
||||||
|
PGID int
|
||||||
|
Timezone string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *System) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *System) lines() (lines []string) {
|
||||||
|
lines = append(lines, lastIndent+"System:")
|
||||||
|
lines = append(lines, indent+lastIndent+"Process user ID: "+strconv.Itoa(settings.PUID))
|
||||||
|
lines = append(lines, indent+lastIndent+"Process group ID: "+strconv.Itoa(settings.PGID))
|
||||||
|
|
||||||
|
if len(settings.Timezone) > 0 {
|
||||||
|
lines = append(lines, indent+lastIndent+"Timezone: "+settings.Timezone)
|
||||||
|
} else {
|
||||||
|
lines = append(lines, indent+lastIndent+"Timezone: NOT SET ⚠️ - it can cause time related issues")
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *System) read(r reader) (err error) {
|
||||||
|
settings.PUID, err = r.env.IntRange("PUID", 0, 65535, params.Default("1000"),
|
||||||
|
params.RetroKeys([]string{"UID"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.PGID, err = r.env.IntRange("PGID", 0, 65535, params.Default("1000"),
|
||||||
|
params.RetroKeys([]string{"GID"}, r.onRetroActive))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Timezone, err = r.env.Get("TZ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
133
internal/configuration/unbound.go
Normal file
133
internal/configuration/unbound.go
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
unbound "github.com/qdm12/dns/pkg/unbound"
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *DNS) readUnbound(r reader) (err error) {
|
||||||
|
if err := settings.readUnboundProviders(r.env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Unbound.ListeningPort = 53
|
||||||
|
|
||||||
|
settings.Unbound.Caching, err = r.env.OnOff("DOT_CACHING", params.Default("on"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Unbound.IPv4 = true
|
||||||
|
|
||||||
|
settings.Unbound.IPv6, err = r.env.OnOff("DOT_IPV6", params.Default("off"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
verbosityLevel, err := r.env.IntRange("DOT_VERBOSITY", 0, 5, params.Default("1"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.Unbound.VerbosityLevel = uint8(verbosityLevel)
|
||||||
|
|
||||||
|
verbosityDetailsLevel, err := r.env.IntRange("DOT_VERBOSITY_DETAILS", 0, 4, params.Default("0"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.Unbound.VerbosityDetailsLevel = uint8(verbosityDetailsLevel)
|
||||||
|
|
||||||
|
validationLogLevel, err := r.env.IntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, params.Default("0"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settings.Unbound.ValidationLogLevel = uint8(validationLogLevel)
|
||||||
|
|
||||||
|
if err := settings.readUnboundPrivateAddresses(r.env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := settings.readUnboundUnblockedHostnames(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Unbound.AccessControl.Allowed = []net.IPNet{
|
||||||
|
{
|
||||||
|
IP: net.IPv4zero,
|
||||||
|
Mask: net.IPv4Mask(0, 0, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IP: net.IPv6zero,
|
||||||
|
Mask: net.IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidDNSOverTLSProvider = errors.New("invalid DNS over TLS provider")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *DNS) readUnboundProviders(env params.Env) (err error) {
|
||||||
|
s, err := env.Get("DOT_PROVIDERS", params.Default("cloudflare"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, provider := range strings.Split(s, ",") {
|
||||||
|
_, ok := unbound.GetProviderData(provider)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("%w: %s", ErrInvalidDNSOverTLSProvider, provider)
|
||||||
|
}
|
||||||
|
settings.Unbound.Providers = append(settings.Unbound.Providers, provider)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidPrivateAddress = errors.New("private address is not a valid IP or CIDR range")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *DNS) readUnboundPrivateAddresses(env params.Env) (err error) {
|
||||||
|
privateAddresses, err := env.CSV("DOT_PRIVATE_ADDRESS")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(privateAddresses) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, address := range privateAddresses {
|
||||||
|
ip := net.ParseIP(address)
|
||||||
|
_, _, err := net.ParseCIDR(address)
|
||||||
|
if ip == nil && err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", ErrInvalidPrivateAddress, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.Unbound.BlockedIPs = append(
|
||||||
|
settings.Unbound.BlockedIPs, privateAddresses...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidHostname = errors.New("invalid hostname")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *DNS) readUnboundUnblockedHostnames(r reader) (err error) {
|
||||||
|
hostnames, err := r.env.CSV("UNBLOCK")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(hostnames) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, hostname := range hostnames {
|
||||||
|
if !r.regex.MatchHostname(hostname) {
|
||||||
|
return fmt.Errorf("%w: %s", ErrInvalidHostname, hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.Unbound.AllowedHostnames = append(
|
||||||
|
settings.Unbound.AllowedHostnames, hostnames...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
66
internal/configuration/updater.go
Normal file
66
internal/configuration/updater.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
Period time.Duration `json:"period"`
|
||||||
|
DNSAddress string `json:"dns_address"`
|
||||||
|
Cyberghost bool `json:"cyberghost"`
|
||||||
|
Mullvad bool `json:"mullvad"`
|
||||||
|
Nordvpn bool `json:"nordvpn"`
|
||||||
|
PIA bool `json:"pia"`
|
||||||
|
Privado bool `json:"privado"`
|
||||||
|
Purevpn bool `json:"purevpn"`
|
||||||
|
Surfshark bool `json:"surfshark"`
|
||||||
|
Vyprvpn bool `json:"vyprvpn"`
|
||||||
|
Windscribe bool `json:"windscribe"`
|
||||||
|
// The two below should be used in CLI mode only
|
||||||
|
Stdout bool `json:"-"` // in order to update constants file (maintainer side)
|
||||||
|
CLI bool `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Updater) String() string {
|
||||||
|
return strings.Join(settings.lines(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Updater) lines() (lines []string) {
|
||||||
|
if settings.Period == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Updater:")
|
||||||
|
|
||||||
|
lines = append(lines, indent+lastIndent+"Period: every "+settings.Period.String())
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Updater) read(r reader) (err error) {
|
||||||
|
settings.Cyberghost = true
|
||||||
|
settings.Mullvad = true
|
||||||
|
settings.Nordvpn = true
|
||||||
|
settings.PIA = true
|
||||||
|
settings.Purevpn = true
|
||||||
|
settings.Surfshark = true
|
||||||
|
settings.Vyprvpn = true
|
||||||
|
settings.Windscribe = true
|
||||||
|
settings.Stdout = false
|
||||||
|
settings.CLI = false
|
||||||
|
// use cloudflare in plaintext to not be blocked by DNS over TLS by default.
|
||||||
|
// If a plaintext address is set in the DNS settings, this one will be used.
|
||||||
|
// TODO use custom future encrypted DNS written in Go without blocking
|
||||||
|
// as it's too much trouble to start another parallel unbound instance for now.
|
||||||
|
settings.DNSAddress = "1.1.1.1"
|
||||||
|
|
||||||
|
settings.Period, err = r.env.Duration("UPDATER_PERIOD", params.Default("0"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
34
internal/configuration/vyprvpn.go
Normal file
34
internal/configuration/vyprvpn.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) vyprvpnLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readVyprvpn(r reader) (err error) {
|
||||||
|
settings.Name = constants.Vyprvpn
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.VyprvpnRegionChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
63
internal/configuration/windscribe.go
Normal file
63
internal/configuration/windscribe.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (settings *Provider) windscribeLines() (lines []string) {
|
||||||
|
if len(settings.ServerSelection.Regions) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.Cities) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Cities: "+commaJoin(settings.ServerSelection.Cities))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(settings.ServerSelection.Hostnames) > 0 {
|
||||||
|
lines = append(lines, lastIndent+"Hostnames: "+commaJoin(settings.ServerSelection.Hostnames))
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, lastIndent+"Custom port: "+strconv.Itoa(int(settings.ServerSelection.CustomPort)))
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func (settings *Provider) readWindscribe(r reader) (err error) {
|
||||||
|
settings.Name = constants.Windscribe
|
||||||
|
|
||||||
|
settings.ServerSelection.Protocol, err = readProtocol(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Regions, err = r.env.CSVInside("REGION", constants.WindscribeRegionChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Cities, err = r.env.CSVInside("CITY", constants.WindscribeCityChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.WindscribeHostnameChoices())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ServerSelection.CustomPort, err = readCustomPort(r.env, settings.ServerSelection.Protocol,
|
||||||
|
[]uint16{21, 22, 80, 123, 143, 443, 587, 1194, 3306, 8080, 54783},
|
||||||
|
[]uint16{53, 80, 123, 443, 1194, 54783})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
5
internal/constants/addresses.go
Normal file
5
internal/constants/addresses.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
const (
|
||||||
|
HealthcheckAddress = "127.0.0.1:9999"
|
||||||
|
)
|
||||||
11
internal/constants/colors.go
Normal file
11
internal/constants/colors.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import "github.com/fatih/color"
|
||||||
|
|
||||||
|
func ColorUnbound() *color.Color {
|
||||||
|
return color.New(color.FgCyan)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ColorOpenvpn() *color.Color {
|
||||||
|
return color.New(color.FgHiMagenta)
|
||||||
|
}
|
||||||
3
internal/constants/constants.go
Normal file
3
internal/constants/constants.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package constants defines constants shared throughout the program.
|
||||||
|
// It also defines constant maps and slices using functions.
|
||||||
|
package constants
|
||||||
254
internal/constants/countries.go
Normal file
254
internal/constants/countries.go
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
func CountryCodes() map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"af": "Afghanistan",
|
||||||
|
"ax": "Aland Islands",
|
||||||
|
"al": "Albania",
|
||||||
|
"dz": "Algeria",
|
||||||
|
"as": "American Samoa",
|
||||||
|
"ad": "Andorra",
|
||||||
|
"ao": "Angola",
|
||||||
|
"ai": "Anguilla",
|
||||||
|
"aq": "Antarctica",
|
||||||
|
"ag": "Antigua and Barbuda",
|
||||||
|
"ar": "Argentina",
|
||||||
|
"am": "Armenia",
|
||||||
|
"aw": "Aruba",
|
||||||
|
"au": "Australia",
|
||||||
|
"at": "Austria",
|
||||||
|
"az": "Azerbaijan",
|
||||||
|
"bs": "Bahamas",
|
||||||
|
"bh": "Bahrain",
|
||||||
|
"bd": "Bangladesh",
|
||||||
|
"bb": "Barbados",
|
||||||
|
"by": "Belarus",
|
||||||
|
"be": "Belgium",
|
||||||
|
"bz": "Belize",
|
||||||
|
"bj": "Benin",
|
||||||
|
"bm": "Bermuda",
|
||||||
|
"bt": "Bhutan",
|
||||||
|
"bo": "Bolivia",
|
||||||
|
"bq": "Bonaire",
|
||||||
|
"ba": "Bosnia and Herzegovina",
|
||||||
|
"bw": "Botswana",
|
||||||
|
"bv": "Bouvet Island",
|
||||||
|
"br": "Brazil",
|
||||||
|
"io": "British Indian Ocean Territory",
|
||||||
|
"vg": "British Virgin Islands",
|
||||||
|
"bn": "Brunei Darussalam",
|
||||||
|
"bg": "Bulgaria",
|
||||||
|
"bf": "Burkina Faso",
|
||||||
|
"bi": "Burundi",
|
||||||
|
"kh": "Cambodia",
|
||||||
|
"cm": "Cameroon",
|
||||||
|
"ca": "Canada",
|
||||||
|
"cv": "Cape Verde",
|
||||||
|
"ky": "Cayman Islands",
|
||||||
|
"cf": "Central African Republic",
|
||||||
|
"td": "Chad",
|
||||||
|
"cl": "Chile",
|
||||||
|
"cn": "China",
|
||||||
|
"cx": "Christmas Island",
|
||||||
|
"cc": "Cocos Islands",
|
||||||
|
"co": "Colombia",
|
||||||
|
"km": "Comoros",
|
||||||
|
"cg": "Congo",
|
||||||
|
"ck": "Cook Islands",
|
||||||
|
"cr": "Costa Rica",
|
||||||
|
"ci": "Cote d'Ivoire",
|
||||||
|
"hr": "Croatia",
|
||||||
|
"cu": "Cuba",
|
||||||
|
"cw": "Curacao",
|
||||||
|
"cy": "Cyprus",
|
||||||
|
"cz": "Czech Republic",
|
||||||
|
"cd": "Democratic Republic of the Congo",
|
||||||
|
"dk": "Denmark",
|
||||||
|
"dj": "Djibouti",
|
||||||
|
"dm": "Dominica",
|
||||||
|
"do": "Dominican Republic",
|
||||||
|
"ec": "Ecuador",
|
||||||
|
"eg": "Egypt",
|
||||||
|
"sv": "El Salvador",
|
||||||
|
"gq": "Equatorial Guinea",
|
||||||
|
"er": "Eritrea",
|
||||||
|
"ee": "Estonia",
|
||||||
|
"et": "Ethiopia",
|
||||||
|
"fk": "Falkland Islands",
|
||||||
|
"fo": "Faroe Islands",
|
||||||
|
"fj": "Fiji",
|
||||||
|
"fi": "Finland",
|
||||||
|
"fr": "France",
|
||||||
|
"gf": "French Guiana",
|
||||||
|
"pf": "French Polynesia",
|
||||||
|
"tf": "French Southern Territories",
|
||||||
|
"ga": "Gabon",
|
||||||
|
"gm": "Gambia",
|
||||||
|
"ge": "Georgia",
|
||||||
|
"de": "Germany",
|
||||||
|
"gh": "Ghana",
|
||||||
|
"gi": "Gibraltar",
|
||||||
|
"gr": "Greece",
|
||||||
|
"gl": "Greenland",
|
||||||
|
"gd": "Grenada",
|
||||||
|
"gp": "Guadeloupe",
|
||||||
|
"gu": "Guam",
|
||||||
|
"gt": "Guatemala",
|
||||||
|
"gg": "Guernsey",
|
||||||
|
"gw": "Guinea-Bissau",
|
||||||
|
"gn": "Guinea",
|
||||||
|
"gy": "Guyana",
|
||||||
|
"ht": "Haiti",
|
||||||
|
"hm": "Heard Island and McDonald Islands",
|
||||||
|
"hn": "Honduras",
|
||||||
|
"hk": "Hong Kong",
|
||||||
|
"hu": "Hungary",
|
||||||
|
"is": "Iceland",
|
||||||
|
"in": "India",
|
||||||
|
"id": "Indonesia",
|
||||||
|
"ir": "Iran",
|
||||||
|
"iq": "Iraq",
|
||||||
|
"ie": "Ireland",
|
||||||
|
"im": "Isle of Man",
|
||||||
|
"il": "Israel",
|
||||||
|
"it": "Italy",
|
||||||
|
"jm": "Jamaica",
|
||||||
|
"jp": "Japan",
|
||||||
|
"je": "Jersey",
|
||||||
|
"jo": "Jordan",
|
||||||
|
"kz": "Kazakhstan",
|
||||||
|
"ke": "Kenya",
|
||||||
|
"ki": "Kiribati",
|
||||||
|
"kr": "Korea",
|
||||||
|
"kw": "Kuwait",
|
||||||
|
"kg": "Kyrgyzstan",
|
||||||
|
"la": "Lao People's Democratic Republic",
|
||||||
|
"lv": "Latvia",
|
||||||
|
"lb": "Lebanon",
|
||||||
|
"ls": "Lesotho",
|
||||||
|
"lr": "Liberia",
|
||||||
|
"ly": "Libya",
|
||||||
|
"li": "Liechtenstein",
|
||||||
|
"lt": "Lithuania",
|
||||||
|
"lu": "Luxembourg",
|
||||||
|
"mo": "Macao",
|
||||||
|
"mk": "Macedonia",
|
||||||
|
"mg": "Madagascar",
|
||||||
|
"mw": "Malawi",
|
||||||
|
"my": "Malaysia",
|
||||||
|
"mv": "Maldives",
|
||||||
|
"ml": "Mali",
|
||||||
|
"mt": "Malta",
|
||||||
|
"mh": "Marshall Islands",
|
||||||
|
"mq": "Martinique",
|
||||||
|
"mr": "Mauritania",
|
||||||
|
"mu": "Mauritius",
|
||||||
|
"yt": "Mayotte",
|
||||||
|
"mx": "Mexico",
|
||||||
|
"fm": "Micronesia",
|
||||||
|
"md": "Moldova",
|
||||||
|
"mc": "Monaco",
|
||||||
|
"mn": "Mongolia",
|
||||||
|
"me": "Montenegro",
|
||||||
|
"ms": "Montserrat",
|
||||||
|
"ma": "Morocco",
|
||||||
|
"mz": "Mozambique",
|
||||||
|
"mm": "Myanmar",
|
||||||
|
"na": "Namibia",
|
||||||
|
"nr": "Nauru",
|
||||||
|
"np": "Nepal",
|
||||||
|
"nl": "Netherlands",
|
||||||
|
"nc": "New Caledonia",
|
||||||
|
"nz": "New Zealand",
|
||||||
|
"ni": "Nicaragua",
|
||||||
|
"ne": "Niger",
|
||||||
|
"ng": "Nigeria",
|
||||||
|
"nu": "Niue",
|
||||||
|
"nf": "Norfolk Island",
|
||||||
|
"mp": "Northern Mariana Islands",
|
||||||
|
"no": "Norway",
|
||||||
|
"om": "Oman",
|
||||||
|
"pk": "Pakistan",
|
||||||
|
"pw": "Palau",
|
||||||
|
"ps": "Palestine, State of",
|
||||||
|
"pa": "Panama",
|
||||||
|
"pg": "Papua New Guinea",
|
||||||
|
"py": "Paraguay",
|
||||||
|
"pe": "Peru",
|
||||||
|
"ph": "Philippines",
|
||||||
|
"pn": "Pitcairn",
|
||||||
|
"pl": "Poland",
|
||||||
|
"pt": "Portugal",
|
||||||
|
"pr": "Puerto Rico",
|
||||||
|
"qa": "Qatar",
|
||||||
|
"re": "Reunion",
|
||||||
|
"ro": "Romania",
|
||||||
|
"ru": "Russian Federation",
|
||||||
|
"rw": "Rwanda",
|
||||||
|
"bl": "Saint Barthelemy",
|
||||||
|
"sh": "Saint Helena",
|
||||||
|
"kn": "Saint Kitts and Nevis",
|
||||||
|
"lc": "Saint Lucia",
|
||||||
|
"mf": "Saint Martin",
|
||||||
|
"pm": "Saint Pierre and Miquelon",
|
||||||
|
"vc": "Saint Vincent and the Grenadines",
|
||||||
|
"ws": "Samoa",
|
||||||
|
"sm": "San Marino",
|
||||||
|
"st": "Sao Tome and Principe",
|
||||||
|
"sa": "Saudi Arabia",
|
||||||
|
"sn": "Senegal",
|
||||||
|
"rs": "Serbia",
|
||||||
|
"sc": "Seychelles",
|
||||||
|
"sl": "Sierra Leone",
|
||||||
|
"sg": "Singapore",
|
||||||
|
"sx": "Sint Maarten",
|
||||||
|
"sk": "Slovakia",
|
||||||
|
"si": "Slovenia",
|
||||||
|
"sb": "Solomon Islands",
|
||||||
|
"so": "Somalia",
|
||||||
|
"za": "South Africa",
|
||||||
|
"gs": "South Georgia and the South Sandwich Islands",
|
||||||
|
"ss": "South Sudan",
|
||||||
|
"es": "Spain",
|
||||||
|
"lk": "Sri Lanka",
|
||||||
|
"sd": "Sudan",
|
||||||
|
"sr": "Suriname",
|
||||||
|
"sj": "Svalbard and Jan Mayen",
|
||||||
|
"sz": "Swaziland",
|
||||||
|
"se": "Sweden",
|
||||||
|
"ch": "Switzerland",
|
||||||
|
"sy": "Syrian Arab Republic",
|
||||||
|
"tw": "Taiwan",
|
||||||
|
"tj": "Tajikistan",
|
||||||
|
"tz": "Tanzania",
|
||||||
|
"th": "Thailand",
|
||||||
|
"tl": "Timor-Leste",
|
||||||
|
"tg": "Togo",
|
||||||
|
"tk": "Tokelau",
|
||||||
|
"to": "Tonga",
|
||||||
|
"tt": "Trinidad and Tobago",
|
||||||
|
"tn": "Tunisia",
|
||||||
|
"tr": "Turkey",
|
||||||
|
"tm": "Turkmenistan",
|
||||||
|
"tc": "Turks and Caicos Islands",
|
||||||
|
"tv": "Tuvalu",
|
||||||
|
"ug": "Uganda",
|
||||||
|
"ua": "Ukraine",
|
||||||
|
"ae": "United Arab Emirates",
|
||||||
|
"gb": "United Kingdom",
|
||||||
|
"um": "United States Minor Outlying Islands",
|
||||||
|
"us": "United States",
|
||||||
|
"uy": "Uruguay",
|
||||||
|
"vi": "US Virgin Islands",
|
||||||
|
"uz": "Uzbekistan",
|
||||||
|
"vu": "Vanuatu",
|
||||||
|
"va": "Vatican City State",
|
||||||
|
"ve": "Venezuela",
|
||||||
|
"vn": "Vietnam",
|
||||||
|
"wf": "Wallis and Futuna",
|
||||||
|
"eh": "Western Sahara",
|
||||||
|
"ye": "Yemen",
|
||||||
|
"zm": "Zambia",
|
||||||
|
"zw": "Zimbabwe",
|
||||||
|
}
|
||||||
|
}
|
||||||
224
internal/constants/cyberghost.go
Normal file
224
internal/constants/cyberghost.go
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
CyberghostCertificate = "MIIGWjCCBEKgAwIBAgIJAJxUG61mxDS7MA0GCSqGSIb3DQEBDQUAMHsxCzAJBgNVBAYTAlJPMRIwEAYDVQQHEwlCdWNoYXJlc3QxGDAWBgNVBAoTD0N5YmVyR2hvc3QgUy5BLjEbMBkGA1UEAxMSQ3liZXJHaG9zdCBSb290IENBMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGN5YmVyZ2hvc3Qucm8wHhcNMTcwNjE5MDgxNzI1WhcNMzcwNjE0MDgxNzI1WjB7MQswCQYDVQQGEwJSTzESMBAGA1UEBxMJQnVjaGFyZXN0MRgwFgYDVQQKEw9DeWJlckdob3N0IFMuQS4xGzAZBgNVBAMTEkN5YmVyR2hvc3QgUm9vdCBDQTEhMB8GCSqGSIb3DQEJARYSaW5mb0BjeWJlcmdob3N0LnJvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7O8+mji2FlQhJXn/G4VLrKPjGtxgQBAdjo0dZEQzKX08q14dLkslmOLgShStWKrOiLXGAvB1rPvvk613jtA0KjQLpgyLy9lIWohQKYjj5jrJYXMZMkbSHBYI9L8L7iezBEFYrjYKdDo51nq99wRFhKdbyKKjDh3e2L2SVEZLT1ogkK5gWzjvH+mjjtjUUicK+YjGwWOz6I+KKaG4Ve/D/cE6nCLbhHIMMnargZEu7sqA6BFeS4kEP/ZdCZoTSX2n43XV1q63nJt/v0KDetbZDciFVW9h9SVPG4qT44p0550N+Mom7zTX7S/ID5T9dplgU8sRGtIMrG0cIMD9zmpFgUnMusCrR7jJFr0sMAveTbgZg95LmstV6R6WKZkSFdUrE0DHl4dHoZvTFX+1LhwhHgjgDLaosX0vhG/C/7LpoVWimd6RRQT3M9o4Fa1TuhfvBzQ20QHrmRV/yKvGNK0xckZ6EZ/QY7Z55ORU15Tgab4ebnblYPWoEmn0mIYP3LFFeoR5OS1EX7+j4kPv+bwPGsmpHjxmZyq2Y7sJBpbOCJgbkn52WZdPBIRDpPdIHQ8pAJC4T0iMK9xvAwWNl/V6EYYNpR97osyEDXn+BTdAHlhJ5fck9KlwI9mb1Kg1bhbvbmaIAiOLenSULYf3j6rI1ygo3R2cCyybtuAq8M7z0OECAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6tdK1g/He5qzjeAoM5eHt4in9iUwga0GA1UdIwSBpTCBooAU6tdK1g/He5qzjeAoM5eHt4in9iWhf6R9MHsxCzAJBgNVBAYTAlJPMRIwEAYDVQQHEwlCdWNoYXJlc3QxGDAWBgNVBAoTD0N5YmVyR2hvc3QgUy5BLjEbMBkGA1UEAxMSQ3liZXJHaG9zdCBSb290IENBMSEwHwYJKoZIhvcNAQkBFhJpbmZvQGN5YmVyZ2hvc3Qucm+CCQCcVButZsQ0uzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4ICAQDNyQ92kj4qiNjnHk99qvnFw9qGfwB9ofaPL74zh0G5hEe3Wgb2o4fqUGnvUNgOu53gJksz3DcPQ8t40wfmm9I1Z8tiM9qrqvkuQ+nKcLgdooXtEsTybPIYDZ2cWR/5E0TKRvC7RFzKgQ4D77Vbi4TdaHiDV7ZNfU1iLCoBGcYm80hcUHEs5KIVLwUmcSOTmbZBySJxcSD0yUpS7nlZGwLY6VQrU+JFwDSisbXT4DXf3iSzp7FzW0/u/SFvWsPHrjE0hkPoZPalYvouaJEHKAhip0ZwSmitlxbBnmm8+K/3c9mLA5/uXrirfpuhhs8V3lyV2mczVtSiTl6gpi88gc//JY80JeHdupjO25T3XEzY9cpxecmkWaUEjLMx4wVoXQuUiPonfILM6OLwi+zUS8gQErdFeGvcQXbncPa4SdJuHkF8lgiX2i8S8fPGdXvU37E9bdAXwP5nZriYq1s0D59Qfvz+vLXVkmyZp6ztxjKjKolemPMak0Y5c1Q4RjNF6tmQoFuy/ACSkWy14Tzu2dFp7UiVbGg1FOvKhfs48zC2/IUQv1arqmPT/9LVq3B2DVT9UKXRUXX/f/jSSsVjkz4uUe2jUyL+XHX1nSmROTPHSAJ+oKf0BLnfqUxFkEUTwLnayssP2nwGgq35b7wEbTFIXdrjHGFUVQIDeERz8UThew=="
|
||||||
|
)
|
||||||
|
|
||||||
|
func CyberghostRegionChoices() (choices []string) {
|
||||||
|
uniqueChoices := map[string]struct{}{}
|
||||||
|
for _, server := range CyberghostServers() {
|
||||||
|
uniqueChoices[server.Region] = struct{}{}
|
||||||
|
}
|
||||||
|
for choice := range uniqueChoices {
|
||||||
|
choices = append(choices, choice)
|
||||||
|
}
|
||||||
|
sort.Slice(choices, func(i, j int) bool {
|
||||||
|
return choices[i] < choices[j]
|
||||||
|
})
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func CyberghostGroupChoices() (choices []string) {
|
||||||
|
uniqueChoices := map[string]struct{}{}
|
||||||
|
for _, server := range CyberghostServers() {
|
||||||
|
uniqueChoices[server.Group] = struct{}{}
|
||||||
|
}
|
||||||
|
for choice := range uniqueChoices {
|
||||||
|
choices = append(choices, choice)
|
||||||
|
}
|
||||||
|
sort.Slice(choices, func(i, j int) bool {
|
||||||
|
return choices[i] < choices[j]
|
||||||
|
})
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
// CyberghostServers returns a slice with the server information for each
|
||||||
|
// of the Cyberghost server.
|
||||||
|
func CyberghostServers() []models.CyberghostServer {
|
||||||
|
return []models.CyberghostServer{
|
||||||
|
{Region: "Albania", Group: "Premium TCP Europe", IPs: []net.IP{{31, 171, 152, 99}, {31, 171, 152, 100}, {31, 171, 152, 101}, {31, 171, 152, 102}, {31, 171, 152, 105}, {31, 171, 152, 108}, {31, 171, 152, 132}, {31, 171, 152, 136}, {31, 171, 152, 139}, {31, 171, 152, 140}}},
|
||||||
|
{Region: "Albania", Group: "Premium UDP Europe", IPs: []net.IP{{31, 171, 152, 102}, {31, 171, 152, 103}, {31, 171, 152, 105}, {31, 171, 152, 106}, {31, 171, 152, 108}, {31, 171, 152, 109}, {31, 171, 152, 110}, {31, 171, 152, 135}, {31, 171, 152, 137}, {31, 171, 152, 139}}},
|
||||||
|
{Region: "Algeria", Group: "Premium UDP Europe", IPs: []net.IP{{176, 125, 228, 131}, {176, 125, 228, 132}, {176, 125, 228, 133}, {176, 125, 228, 134}, {176, 125, 228, 135}, {176, 125, 228, 136}, {176, 125, 228, 137}, {176, 125, 228, 140}, {176, 125, 228, 142}, {176, 125, 228, 143}}},
|
||||||
|
{Region: "Algeria", Group: "Premium TCP Europe", IPs: []net.IP{{176, 125, 228, 131}, {176, 125, 228, 132}, {176, 125, 228, 133}, {176, 125, 228, 134}, {176, 125, 228, 136}, {176, 125, 228, 139}, {176, 125, 228, 140}, {176, 125, 228, 141}, {176, 125, 228, 142}, {176, 125, 228, 143}}},
|
||||||
|
{Region: "Andorra", Group: "Premium UDP Europe", IPs: []net.IP{{188, 241, 82, 132}, {188, 241, 82, 133}, {188, 241, 82, 135}, {188, 241, 82, 138}, {188, 241, 82, 141}, {188, 241, 82, 144}, {188, 241, 82, 146}, {188, 241, 82, 157}, {188, 241, 82, 159}, {188, 241, 82, 166}}},
|
||||||
|
{Region: "Andorra", Group: "Premium TCP Europe", IPs: []net.IP{{188, 241, 82, 135}, {188, 241, 82, 136}, {188, 241, 82, 140}, {188, 241, 82, 142}, {188, 241, 82, 149}, {188, 241, 82, 151}, {188, 241, 82, 154}, {188, 241, 82, 160}, {188, 241, 82, 163}, {188, 241, 82, 165}}},
|
||||||
|
{Region: "Argentina", Group: "Premium UDP USA", IPs: []net.IP{{190, 106, 130, 15}, {190, 106, 130, 16}, {190, 106, 130, 20}, {190, 106, 130, 21}, {190, 106, 130, 22}, {190, 106, 130, 23}, {190, 106, 130, 37}, {190, 106, 130, 39}, {190, 106, 130, 43}, {190, 106, 130, 44}}},
|
||||||
|
{Region: "Argentina", Group: "Premium TCP USA", IPs: []net.IP{{190, 106, 130, 16}, {190, 106, 130, 17}, {190, 106, 130, 18}, {190, 106, 130, 26}, {190, 106, 130, 38}, {190, 106, 130, 40}, {190, 106, 130, 41}, {190, 106, 130, 42}, {190, 106, 130, 45}, {190, 106, 130, 52}}},
|
||||||
|
{Region: "Armenia", Group: "Premium UDP Europe", IPs: []net.IP{{185, 253, 160, 131}, {185, 253, 160, 132}, {185, 253, 160, 134}, {185, 253, 160, 135}, {185, 253, 160, 136}, {185, 253, 160, 137}, {185, 253, 160, 138}, {185, 253, 160, 139}, {185, 253, 160, 141}, {185, 253, 160, 144}}},
|
||||||
|
{Region: "Armenia", Group: "Premium TCP Europe", IPs: []net.IP{{185, 253, 160, 133}, {185, 253, 160, 134}, {185, 253, 160, 136}, {185, 253, 160, 137}, {185, 253, 160, 138}, {185, 253, 160, 139}, {185, 253, 160, 140}, {185, 253, 160, 141}, {185, 253, 160, 143}, {185, 253, 160, 144}}},
|
||||||
|
{Region: "Australia", Group: "Premium TCP Asia", IPs: []net.IP{{43, 242, 68, 111}, {43, 242, 68, 113}, {43, 242, 68, 120}, {202, 60, 80, 16}, {202, 60, 80, 72}, {202, 60, 80, 96}, {202, 60, 80, 151}, {202, 60, 80, 172}, {202, 60, 80, 173}, {202, 60, 80, 178}}},
|
||||||
|
{Region: "Australia", Group: "Premium UDP Asia", IPs: []net.IP{{43, 242, 68, 83}, {43, 242, 68, 94}, {202, 60, 80, 11}, {202, 60, 80, 21}, {202, 60, 80, 69}, {202, 60, 80, 107}, {202, 60, 80, 122}, {202, 60, 80, 123}, {202, 60, 80, 132}, {202, 60, 80, 162}}},
|
||||||
|
{Region: "Austria", Group: "Premium TCP Europe", IPs: []net.IP{{89, 187, 168, 134}, {89, 187, 168, 139}, {89, 187, 168, 140}, {89, 187, 168, 145}, {89, 187, 168, 146}, {89, 187, 168, 150}, {89, 187, 168, 167}, {89, 187, 168, 169}, {89, 187, 168, 180}, {89, 187, 168, 182}}},
|
||||||
|
{Region: "Austria", Group: "Premium UDP Europe", IPs: []net.IP{{89, 187, 168, 131}, {89, 187, 168, 132}, {89, 187, 168, 144}, {89, 187, 168, 147}, {89, 187, 168, 150}, {89, 187, 168, 151}, {89, 187, 168, 152}, {89, 187, 168, 163}, {89, 187, 168, 175}, {89, 187, 168, 177}}},
|
||||||
|
{Region: "Bahamas", Group: "Premium TCP USA", IPs: []net.IP{{95, 181, 238, 131}, {95, 181, 238, 132}, {95, 181, 238, 137}, {95, 181, 238, 139}, {95, 181, 238, 140}, {95, 181, 238, 141}, {95, 181, 238, 144}, {95, 181, 238, 146}, {95, 181, 238, 147}, {95, 181, 238, 153}}},
|
||||||
|
{Region: "Bahamas", Group: "Premium UDP USA", IPs: []net.IP{{95, 181, 238, 131}, {95, 181, 238, 133}, {95, 181, 238, 137}, {95, 181, 238, 138}, {95, 181, 238, 140}, {95, 181, 238, 141}, {95, 181, 238, 142}, {95, 181, 238, 146}, {95, 181, 238, 152}, {95, 181, 238, 153}}},
|
||||||
|
{Region: "Bangladesh", Group: "Premium UDP Asia", IPs: []net.IP{{84, 252, 93, 131}, {84, 252, 93, 132}, {84, 252, 93, 133}, {84, 252, 93, 134}, {84, 252, 93, 137}, {84, 252, 93, 140}, {84, 252, 93, 142}, {84, 252, 93, 143}, {84, 252, 93, 144}, {84, 252, 93, 145}}},
|
||||||
|
{Region: "Bangladesh", Group: "Premium TCP Asia", IPs: []net.IP{{84, 252, 93, 131}, {84, 252, 93, 132}, {84, 252, 93, 135}, {84, 252, 93, 136}, {84, 252, 93, 139}, {84, 252, 93, 140}, {84, 252, 93, 141}, {84, 252, 93, 142}, {84, 252, 93, 144}, {84, 252, 93, 145}}},
|
||||||
|
{Region: "Belarus", Group: "Premium UDP Europe", IPs: []net.IP{{45, 132, 194, 5}, {45, 132, 194, 6}, {45, 132, 194, 10}, {45, 132, 194, 13}, {45, 132, 194, 14}, {45, 132, 194, 20}, {45, 132, 194, 22}, {45, 132, 194, 23}, {45, 132, 194, 38}, {45, 132, 194, 48}}},
|
||||||
|
{Region: "Belarus", Group: "Premium TCP Europe", IPs: []net.IP{{45, 132, 194, 3}, {45, 132, 194, 5}, {45, 132, 194, 7}, {45, 132, 194, 10}, {45, 132, 194, 15}, {45, 132, 194, 35}, {45, 132, 194, 37}, {45, 132, 194, 40}, {45, 132, 194, 43}, {45, 132, 194, 47}}},
|
||||||
|
{Region: "Belgium", Group: "Premium UDP Europe", IPs: []net.IP{{185, 210, 217, 14}, {185, 232, 21, 119}, {193, 9, 114, 211}, {193, 9, 114, 221}, {194, 110, 115, 201}, {194, 110, 115, 214}, {194, 110, 115, 216}, {194, 110, 115, 220}, {194, 110, 115, 221}, {194, 110, 115, 233}}},
|
||||||
|
{Region: "Belgium", Group: "Premium TCP Europe", IPs: []net.IP{{5, 253, 205, 27}, {37, 120, 143, 58}, {37, 120, 143, 59}, {37, 120, 143, 165}, {185, 210, 217, 60}, {185, 232, 21, 115}, {185, 232, 21, 118}, {193, 9, 114, 228}, {194, 110, 115, 215}, {194, 110, 115, 232}}},
|
||||||
|
{Region: "Bosnia and Herzegovina", Group: "Premium UDP Europe", IPs: []net.IP{{185, 99, 3, 57}, {185, 99, 3, 58}, {185, 99, 3, 72}, {185, 99, 3, 73}, {185, 99, 3, 74}, {185, 99, 3, 130}, {185, 99, 3, 131}, {185, 99, 3, 134}, {185, 99, 3, 135}, {185, 99, 3, 136}}},
|
||||||
|
{Region: "Bosnia and Herzegovina", Group: "Premium TCP Europe", IPs: []net.IP{{185, 99, 3, 57}, {185, 99, 3, 58}, {185, 99, 3, 72}, {185, 99, 3, 73}, {185, 99, 3, 74}, {185, 99, 3, 130}, {185, 99, 3, 131}, {185, 99, 3, 134}, {185, 99, 3, 135}, {185, 99, 3, 136}}},
|
||||||
|
{Region: "Brazil", Group: "Premium UDP USA", IPs: []net.IP{{188, 241, 177, 8}, {188, 241, 177, 10}, {188, 241, 177, 12}, {188, 241, 177, 13}, {188, 241, 177, 14}, {188, 241, 177, 30}, {188, 241, 177, 36}, {188, 241, 177, 42}, {188, 241, 177, 45}, {188, 241, 177, 46}}},
|
||||||
|
{Region: "Brazil", Group: "Premium TCP USA", IPs: []net.IP{{188, 241, 177, 9}, {188, 241, 177, 12}, {188, 241, 177, 13}, {188, 241, 177, 19}, {188, 241, 177, 29}, {188, 241, 177, 35}, {188, 241, 177, 40}, {188, 241, 177, 41}, {188, 241, 177, 43}, {188, 241, 177, 44}}},
|
||||||
|
{Region: "Bulgaria", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 152, 100}, {37, 120, 152, 101}, {37, 120, 152, 102}, {37, 120, 152, 103}, {37, 120, 152, 104}, {37, 120, 152, 105}, {37, 120, 152, 106}, {37, 120, 152, 108}, {37, 120, 152, 109}, {37, 120, 152, 110}}},
|
||||||
|
{Region: "Bulgaria", Group: "Premium TCP Europe", IPs: []net.IP{{37, 120, 152, 99}, {37, 120, 152, 100}, {37, 120, 152, 101}, {37, 120, 152, 102}, {37, 120, 152, 104}, {37, 120, 152, 105}, {37, 120, 152, 106}, {37, 120, 152, 107}, {37, 120, 152, 108}, {37, 120, 152, 109}}},
|
||||||
|
{Region: "Cambodia", Group: "Premium TCP Asia", IPs: []net.IP{{188, 215, 235, 37}, {188, 215, 235, 41}, {188, 215, 235, 45}, {188, 215, 235, 46}, {188, 215, 235, 47}, {188, 215, 235, 49}, {188, 215, 235, 52}, {188, 215, 235, 53}, {188, 215, 235, 54}, {188, 215, 235, 57}}},
|
||||||
|
{Region: "Cambodia", Group: "Premium UDP Asia", IPs: []net.IP{{188, 215, 235, 36}, {188, 215, 235, 37}, {188, 215, 235, 40}, {188, 215, 235, 41}, {188, 215, 235, 45}, {188, 215, 235, 47}, {188, 215, 235, 50}, {188, 215, 235, 51}, {188, 215, 235, 56}, {188, 215, 235, 57}}},
|
||||||
|
{Region: "Canada", Group: "Premium TCP USA", IPs: []net.IP{{37, 120, 205, 4}, {37, 120, 205, 26}, {66, 115, 142, 171}, {89, 47, 234, 103}, {176, 113, 74, 22}, {176, 113, 74, 77}, {176, 113, 74, 135}, {176, 113, 74, 137}, {176, 113, 74, 201}, {176, 113, 74, 205}}},
|
||||||
|
{Region: "Canada", Group: "Premium UDP USA", IPs: []net.IP{{37, 120, 205, 24}, {66, 115, 142, 162}, {66, 115, 142, 172}, {89, 47, 234, 85}, {89, 47, 234, 118}, {172, 98, 89, 146}, {172, 98, 89, 159}, {172, 98, 89, 172}, {176, 113, 74, 156}, {176, 113, 74, 206}}},
|
||||||
|
{Region: "China", Group: "Premium TCP Asia", IPs: []net.IP{{188, 241, 80, 131}, {188, 241, 80, 132}, {188, 241, 80, 133}, {188, 241, 80, 134}, {188, 241, 80, 136}, {188, 241, 80, 137}, {188, 241, 80, 139}, {188, 241, 80, 140}, {188, 241, 80, 141}, {188, 241, 80, 142}}},
|
||||||
|
{Region: "China", Group: "Premium UDP Asia", IPs: []net.IP{{188, 241, 80, 132}, {188, 241, 80, 133}, {188, 241, 80, 134}, {188, 241, 80, 135}, {188, 241, 80, 136}, {188, 241, 80, 137}, {188, 241, 80, 138}, {188, 241, 80, 139}, {188, 241, 80, 140}, {188, 241, 80, 141}}},
|
||||||
|
{Region: "Costa Rica", Group: "Premium TCP USA", IPs: []net.IP{{143, 202, 160, 67}, {143, 202, 160, 68}, {143, 202, 160, 69}, {143, 202, 160, 70}, {143, 202, 160, 72}, {143, 202, 160, 73}, {143, 202, 160, 74}, {143, 202, 160, 75}, {143, 202, 160, 76}, {143, 202, 160, 78}}},
|
||||||
|
{Region: "Cyprus", Group: "Premium UDP Europe", IPs: []net.IP{{185, 253, 162, 131}, {185, 253, 162, 134}, {185, 253, 162, 136}, {185, 253, 162, 137}, {185, 253, 162, 139}, {185, 253, 162, 140}, {185, 253, 162, 141}, {185, 253, 162, 142}, {185, 253, 162, 143}, {185, 253, 162, 144}}},
|
||||||
|
{Region: "Cyprus", Group: "Premium TCP Europe", IPs: []net.IP{{185, 253, 162, 131}, {185, 253, 162, 132}, {185, 253, 162, 134}, {185, 253, 162, 135}, {185, 253, 162, 136}, {185, 253, 162, 139}, {185, 253, 162, 140}, {185, 253, 162, 141}, {185, 253, 162, 143}, {185, 253, 162, 144}}},
|
||||||
|
{Region: "Czech Republic", Group: "Premium TCP Europe", IPs: []net.IP{{185, 216, 35, 231}, {185, 216, 35, 236}, {195, 181, 161, 3}, {195, 181, 161, 7}, {195, 181, 161, 11}, {195, 181, 161, 14}, {195, 181, 161, 15}, {195, 181, 161, 16}, {195, 181, 161, 17}, {195, 181, 161, 22}}},
|
||||||
|
{Region: "Czech Republic", Group: "Premium UDP Europe", IPs: []net.IP{{185, 216, 35, 227}, {185, 216, 35, 235}, {195, 181, 161, 3}, {195, 181, 161, 5}, {195, 181, 161, 7}, {195, 181, 161, 11}, {195, 181, 161, 12}, {195, 181, 161, 14}, {195, 181, 161, 15}, {195, 181, 161, 20}}},
|
||||||
|
{Region: "Denmark", Group: "Premium TCP Europe", IPs: []net.IP{{37, 120, 145, 86}, {37, 120, 194, 45}, {37, 120, 194, 46}, {37, 120, 194, 61}, {95, 174, 65, 172}, {95, 174, 65, 174}, {185, 206, 224, 237}, {185, 206, 224, 244}, {185, 206, 224, 245}, {185, 206, 224, 246}}},
|
||||||
|
{Region: "Denmark", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 194, 56}, {37, 120, 194, 61}, {95, 174, 65, 164}, {95, 174, 65, 165}, {95, 174, 65, 167}, {95, 174, 65, 172}, {185, 206, 224, 235}, {185, 206, 224, 244}, {185, 206, 224, 247}, {185, 206, 224, 249}}},
|
||||||
|
{Region: "Egypt", Group: "Premium TCP Europe", IPs: []net.IP{{188, 214, 122, 37}, {188, 214, 122, 39}, {188, 214, 122, 40}, {188, 214, 122, 51}, {188, 214, 122, 53}, {188, 214, 122, 54}, {188, 214, 122, 56}, {188, 214, 122, 58}, {188, 214, 122, 59}, {188, 214, 122, 62}}},
|
||||||
|
{Region: "Egypt", Group: "Premium UDP Europe", IPs: []net.IP{{188, 214, 122, 35}, {188, 214, 122, 38}, {188, 214, 122, 39}, {188, 214, 122, 44}, {188, 214, 122, 46}, {188, 214, 122, 48}, {188, 214, 122, 50}, {188, 214, 122, 52}, {188, 214, 122, 54}, {188, 214, 122, 58}}},
|
||||||
|
{Region: "Estonia", Group: "Premium TCP Europe", IPs: []net.IP{{95, 153, 31, 82}, {95, 153, 31, 83}, {95, 153, 31, 84}, {95, 153, 31, 85}, {95, 153, 31, 86}, {95, 153, 31, 87}, {95, 153, 31, 89}, {95, 153, 31, 90}, {95, 153, 31, 92}, {95, 153, 31, 93}}},
|
||||||
|
{Region: "Estonia", Group: "Premium UDP Europe", IPs: []net.IP{{95, 153, 31, 83}, {95, 153, 31, 84}, {95, 153, 31, 85}, {95, 153, 31, 86}, {95, 153, 31, 87}, {95, 153, 31, 88}, {95, 153, 31, 90}, {95, 153, 31, 92}, {95, 153, 31, 93}, {95, 153, 31, 94}}},
|
||||||
|
{Region: "Finland", Group: "Premium UDP Europe", IPs: []net.IP{{188, 126, 89, 133}, {188, 126, 89, 134}, {188, 126, 89, 137}, {188, 126, 89, 138}, {188, 126, 89, 143}, {188, 126, 89, 144}, {188, 126, 89, 149}, {188, 126, 89, 150}, {188, 126, 89, 152}, {188, 126, 89, 154}}},
|
||||||
|
{Region: "Finland", Group: "Premium TCP Europe", IPs: []net.IP{{188, 126, 89, 131}, {188, 126, 89, 132}, {188, 126, 89, 133}, {188, 126, 89, 137}, {188, 126, 89, 138}, {188, 126, 89, 142}, {188, 126, 89, 145}, {188, 126, 89, 153}, {188, 126, 89, 154}, {188, 126, 89, 155}}},
|
||||||
|
{Region: "France", Group: "Premium UDP Europe", IPs: []net.IP{{84, 17, 60, 31}, {84, 17, 60, 93}, {84, 17, 60, 136}, {84, 17, 60, 173}, {84, 17, 60, 177}, {84, 17, 60, 184}, {84, 17, 61, 10}, {84, 17, 61, 92}, {84, 17, 61, 155}, {138, 199, 26, 174}}},
|
||||||
|
{Region: "France", Group: "Premium TCP Europe", IPs: []net.IP{{84, 17, 60, 40}, {84, 17, 60, 85}, {84, 17, 60, 98}, {84, 17, 60, 150}, {84, 17, 60, 178}, {84, 17, 61, 5}, {84, 17, 61, 212}, {138, 199, 26, 76}, {138, 199, 26, 147}, {138, 199, 26, 219}}},
|
||||||
|
{Region: "Georgia", Group: "Premium TCP Europe", IPs: []net.IP{{95, 181, 236, 131}, {95, 181, 236, 132}, {95, 181, 236, 133}, {95, 181, 236, 135}, {95, 181, 236, 137}, {95, 181, 236, 138}, {95, 181, 236, 139}, {95, 181, 236, 140}, {95, 181, 236, 142}, {95, 181, 236, 144}}},
|
||||||
|
{Region: "Georgia", Group: "Premium UDP Europe", IPs: []net.IP{{95, 181, 236, 131}, {95, 181, 236, 132}, {95, 181, 236, 133}, {95, 181, 236, 134}, {95, 181, 236, 138}, {95, 181, 236, 139}, {95, 181, 236, 140}, {95, 181, 236, 141}, {95, 181, 236, 143}, {95, 181, 236, 144}}},
|
||||||
|
{Region: "Germany", Group: "Premium TCP Europe", IPs: []net.IP{{37, 120, 217, 30}, {37, 120, 217, 61}, {84, 17, 48, 13}, {84, 17, 48, 18}, {84, 17, 48, 22}, {84, 17, 48, 81}, {84, 17, 48, 185}, {84, 17, 49, 242}, {154, 28, 188, 128}, {154, 28, 188, 167}}},
|
||||||
|
{Region: "Germany", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 217, 38}, {84, 17, 48, 55}, {84, 17, 48, 140}, {84, 17, 48, 188}, {84, 17, 48, 192}, {84, 17, 48, 205}, {84, 17, 49, 128}, {84, 17, 49, 191}, {84, 17, 49, 236}, {154, 28, 188, 82}}},
|
||||||
|
{Region: "Greece", Group: "Premium UDP Europe", IPs: []net.IP{{154, 57, 3, 131}, {154, 57, 3, 133}, {154, 57, 3, 136}, {154, 57, 3, 137}, {154, 57, 3, 140}, {154, 57, 3, 141}, {188, 123, 126, 167}, {188, 123, 126, 171}, {188, 123, 126, 175}, {188, 123, 126, 176}}},
|
||||||
|
{Region: "Greece", Group: "Premium TCP Europe", IPs: []net.IP{{154, 57, 3, 131}, {154, 57, 3, 133}, {154, 57, 3, 134}, {154, 57, 3, 137}, {154, 57, 3, 139}, {188, 123, 126, 170}, {188, 123, 126, 172}, {188, 123, 126, 173}, {188, 123, 126, 175}, {188, 123, 126, 177}}},
|
||||||
|
{Region: "Greenland", Group: "Premium UDP Europe", IPs: []net.IP{{91, 90, 120, 3}, {91, 90, 120, 5}, {91, 90, 120, 6}, {91, 90, 120, 7}, {91, 90, 120, 8}, {91, 90, 120, 9}, {91, 90, 120, 10}, {91, 90, 120, 14}, {91, 90, 120, 15}, {91, 90, 120, 17}}},
|
||||||
|
{Region: "Greenland", Group: "Premium TCP Europe", IPs: []net.IP{{91, 90, 120, 3}, {91, 90, 120, 4}, {91, 90, 120, 5}, {91, 90, 120, 6}, {91, 90, 120, 9}, {91, 90, 120, 10}, {91, 90, 120, 11}, {91, 90, 120, 13}, {91, 90, 120, 14}, {91, 90, 120, 17}}},
|
||||||
|
{Region: "Hong Kong", Group: "Premium TCP Asia", IPs: []net.IP{{84, 17, 56, 34}, {84, 17, 56, 41}, {84, 17, 56, 133}, {84, 17, 56, 147}, {84, 17, 56, 148}, {84, 17, 56, 153}, {84, 17, 56, 163}, {84, 17, 56, 167}, {84, 17, 56, 171}, {84, 17, 56, 184}}},
|
||||||
|
{Region: "Hong Kong", Group: "Premium UDP Asia", IPs: []net.IP{{84, 17, 56, 39}, {84, 17, 56, 52}, {84, 17, 56, 55}, {84, 17, 56, 135}, {84, 17, 56, 136}, {84, 17, 56, 145}, {84, 17, 56, 149}, {84, 17, 56, 165}, {84, 17, 56, 167}, {84, 17, 56, 170}}},
|
||||||
|
{Region: "Hungary", Group: "Premium TCP Europe", IPs: []net.IP{{86, 106, 74, 243}, {86, 106, 74, 244}, {86, 106, 74, 247}, {86, 106, 74, 251}, {86, 106, 74, 252}, {86, 106, 74, 253}, {185, 189, 114, 117}, {185, 189, 114, 119}, {185, 189, 114, 124}, {185, 189, 114, 126}}},
|
||||||
|
{Region: "Hungary", Group: "Premium UDP Europe", IPs: []net.IP{{86, 106, 74, 252}, {86, 106, 74, 253}, {86, 106, 74, 254}, {185, 189, 114, 116}, {185, 189, 114, 117}, {185, 189, 114, 118}, {185, 189, 114, 121}, {185, 189, 114, 123}, {185, 189, 114, 125}, {185, 189, 114, 126}}},
|
||||||
|
{Region: "Iceland", Group: "Premium UDP Europe", IPs: []net.IP{{45, 133, 193, 4}, {45, 133, 193, 5}, {45, 133, 193, 6}, {45, 133, 193, 8}, {45, 133, 193, 9}, {45, 133, 193, 10}, {45, 133, 193, 11}, {45, 133, 193, 12}, {45, 133, 193, 13}, {45, 133, 193, 14}}},
|
||||||
|
{Region: "Iceland", Group: "Premium TCP Europe", IPs: []net.IP{{45, 133, 193, 3}, {45, 133, 193, 4}, {45, 133, 193, 5}, {45, 133, 193, 6}, {45, 133, 193, 7}, {45, 133, 193, 8}, {45, 133, 193, 9}, {45, 133, 193, 10}, {45, 133, 193, 11}, {45, 133, 193, 13}}},
|
||||||
|
{Region: "India", Group: "Premium TCP Europe", IPs: []net.IP{{43, 241, 71, 117}, {43, 241, 71, 118}, {43, 241, 71, 122}, {43, 241, 71, 123}, {43, 241, 71, 125}, {43, 241, 71, 148}, {43, 241, 71, 151}, {43, 241, 71, 152}, {43, 241, 71, 154}, {43, 241, 71, 156}}},
|
||||||
|
{Region: "India", Group: "Premium UDP Europe", IPs: []net.IP{{43, 241, 71, 115}, {43, 241, 71, 119}, {43, 241, 71, 123}, {43, 241, 71, 124}, {43, 241, 71, 148}, {43, 241, 71, 149}, {43, 241, 71, 151}, {43, 241, 71, 153}, {43, 241, 71, 155}, {43, 241, 71, 157}}},
|
||||||
|
{Region: "Indonesia", Group: "Premium TCP Asia", IPs: []net.IP{{113, 20, 29, 243}, {113, 20, 29, 244}, {113, 20, 29, 245}, {113, 20, 29, 246}, {113, 20, 29, 247}, {113, 20, 29, 249}, {113, 20, 29, 250}, {113, 20, 29, 252}, {113, 20, 29, 253}, {113, 20, 29, 254}}},
|
||||||
|
{Region: "Indonesia", Group: "Premium UDP Asia", IPs: []net.IP{{113, 20, 29, 243}, {113, 20, 29, 244}, {113, 20, 29, 245}, {113, 20, 29, 246}, {113, 20, 29, 247}, {113, 20, 29, 248}, {113, 20, 29, 249}, {113, 20, 29, 250}, {113, 20, 29, 251}, {113, 20, 29, 253}}},
|
||||||
|
{Region: "Iran", Group: "Premium UDP Asia", IPs: []net.IP{{62, 133, 46, 3}, {62, 133, 46, 5}, {62, 133, 46, 7}, {62, 133, 46, 8}, {62, 133, 46, 9}, {62, 133, 46, 11}, {62, 133, 46, 12}, {62, 133, 46, 13}, {62, 133, 46, 14}, {62, 133, 46, 15}}},
|
||||||
|
{Region: "Iran", Group: "Premium TCP Asia", IPs: []net.IP{{62, 133, 46, 3}, {62, 133, 46, 6}, {62, 133, 46, 7}, {62, 133, 46, 8}, {62, 133, 46, 9}, {62, 133, 46, 10}, {62, 133, 46, 11}, {62, 133, 46, 12}, {62, 133, 46, 14}, {62, 133, 46, 15}}},
|
||||||
|
{Region: "Ireland", Group: "Premium UDP Europe", IPs: []net.IP{{77, 81, 139, 35}, {77, 81, 139, 40}, {77, 81, 139, 41}, {77, 81, 139, 45}, {84, 247, 48, 3}, {84, 247, 48, 8}, {84, 247, 48, 10}, {84, 247, 48, 19}, {84, 247, 48, 21}, {84, 247, 48, 29}}},
|
||||||
|
{Region: "Ireland", Group: "Premium TCP Europe", IPs: []net.IP{{77, 81, 139, 40}, {84, 247, 48, 3}, {84, 247, 48, 4}, {84, 247, 48, 7}, {84, 247, 48, 10}, {84, 247, 48, 20}, {84, 247, 48, 23}, {84, 247, 48, 24}, {84, 247, 48, 26}, {84, 247, 48, 30}}},
|
||||||
|
{Region: "Isle of Man", Group: "Premium TCP Europe", IPs: []net.IP{{91, 90, 124, 147}, {91, 90, 124, 148}, {91, 90, 124, 149}, {91, 90, 124, 152}, {91, 90, 124, 153}, {91, 90, 124, 155}, {91, 90, 124, 156}, {91, 90, 124, 157}, {91, 90, 124, 158}, {91, 90, 124, 159}}},
|
||||||
|
{Region: "Isle of Man", Group: "Premium UDP Europe", IPs: []net.IP{{91, 90, 124, 148}, {91, 90, 124, 149}, {91, 90, 124, 150}, {91, 90, 124, 152}, {91, 90, 124, 153}, {91, 90, 124, 154}, {91, 90, 124, 155}, {91, 90, 124, 157}, {91, 90, 124, 158}, {91, 90, 124, 159}}},
|
||||||
|
{Region: "Israel", Group: "Premium TCP Europe", IPs: []net.IP{{160, 116, 0, 163}, {160, 116, 0, 164}, {160, 116, 0, 165}, {160, 116, 0, 166}, {160, 116, 0, 168}, {160, 116, 0, 169}, {160, 116, 0, 170}, {160, 116, 0, 171}, {160, 116, 0, 172}, {160, 116, 0, 174}}},
|
||||||
|
{Region: "Israel", Group: "Premium UDP Europe", IPs: []net.IP{{160, 116, 0, 163}, {160, 116, 0, 164}, {160, 116, 0, 165}, {160, 116, 0, 166}, {160, 116, 0, 167}, {160, 116, 0, 168}, {160, 116, 0, 169}, {160, 116, 0, 170}, {160, 116, 0, 171}, {160, 116, 0, 172}}},
|
||||||
|
{Region: "Italy", Group: "Premium UDP Europe", IPs: []net.IP{{84, 17, 58, 21}, {84, 17, 58, 94}, {87, 101, 94, 68}, {185, 217, 71, 132}, {185, 217, 71, 135}, {185, 217, 71, 154}, {212, 102, 55, 97}, {212, 102, 55, 111}, {212, 102, 55, 113}, {212, 102, 55, 118}}},
|
||||||
|
{Region: "Italy", Group: "Premium TCP Europe", IPs: []net.IP{{84, 17, 58, 13}, {84, 17, 58, 22}, {84, 17, 58, 23}, {84, 17, 58, 110}, {185, 217, 71, 134}, {185, 217, 71, 155}, {212, 102, 55, 97}, {212, 102, 55, 104}, {212, 102, 55, 114}, {212, 102, 55, 118}}},
|
||||||
|
{Region: "Japan", Group: "Premium UDP Asia", IPs: []net.IP{{156, 146, 35, 7}, {156, 146, 35, 8}, {156, 146, 35, 10}, {156, 146, 35, 12}, {156, 146, 35, 13}, {156, 146, 35, 14}, {156, 146, 35, 15}, {156, 146, 35, 16}, {156, 146, 35, 22}, {156, 146, 35, 49}}},
|
||||||
|
{Region: "Japan", Group: "Premium TCP Asia", IPs: []net.IP{{156, 146, 35, 4}, {156, 146, 35, 6}, {156, 146, 35, 9}, {156, 146, 35, 12}, {156, 146, 35, 16}, {156, 146, 35, 21}, {156, 146, 35, 22}, {156, 146, 35, 28}, {156, 146, 35, 29}, {156, 146, 35, 49}}},
|
||||||
|
{Region: "Kazakhstan", Group: "Premium UDP Europe", IPs: []net.IP{{62, 133, 47, 131}, {62, 133, 47, 132}, {62, 133, 47, 133}, {62, 133, 47, 134}, {62, 133, 47, 135}, {62, 133, 47, 137}, {62, 133, 47, 139}, {62, 133, 47, 140}, {62, 133, 47, 143}, {62, 133, 47, 144}}},
|
||||||
|
{Region: "Kazakhstan", Group: "Premium TCP Europe", IPs: []net.IP{{62, 133, 47, 132}, {62, 133, 47, 133}, {62, 133, 47, 135}, {62, 133, 47, 137}, {62, 133, 47, 138}, {62, 133, 47, 140}, {62, 133, 47, 141}, {62, 133, 47, 142}, {62, 133, 47, 143}, {62, 133, 47, 144}}},
|
||||||
|
{Region: "Kenya", Group: "Premium TCP Asia", IPs: []net.IP{{62, 12, 118, 195}, {62, 12, 118, 196}, {62, 12, 118, 197}, {62, 12, 118, 198}, {62, 12, 118, 199}, {62, 12, 118, 200}, {62, 12, 118, 201}, {62, 12, 118, 202}, {62, 12, 118, 203}, {62, 12, 118, 204}}},
|
||||||
|
{Region: "Kenya", Group: "Premium UDP Asia", IPs: []net.IP{{62, 12, 118, 195}, {62, 12, 118, 196}, {62, 12, 118, 197}, {62, 12, 118, 198}, {62, 12, 118, 199}, {62, 12, 118, 200}, {62, 12, 118, 201}, {62, 12, 118, 202}, {62, 12, 118, 203}, {62, 12, 118, 204}}},
|
||||||
|
{Region: "Korea", Group: "Premium TCP Asia", IPs: []net.IP{{27, 255, 75, 227}, {27, 255, 75, 228}, {27, 255, 75, 229}, {27, 255, 75, 238}, {27, 255, 75, 243}, {27, 255, 75, 245}, {27, 255, 75, 246}, {27, 255, 75, 249}, {27, 255, 75, 252}, {27, 255, 75, 254}}},
|
||||||
|
{Region: "Korea", Group: "Premium UDP Asia", IPs: []net.IP{{27, 255, 75, 227}, {27, 255, 75, 229}, {27, 255, 75, 231}, {27, 255, 75, 232}, {27, 255, 75, 234}, {27, 255, 75, 235}, {27, 255, 75, 236}, {27, 255, 75, 245}, {27, 255, 75, 247}, {27, 255, 75, 253}}},
|
||||||
|
{Region: "Latvia", Group: "Premium UDP Europe", IPs: []net.IP{{109, 248, 148, 245}, {109, 248, 148, 247}, {109, 248, 148, 252}, {109, 248, 148, 254}, {109, 248, 149, 20}, {109, 248, 149, 21}, {109, 248, 149, 27}, {109, 248, 149, 28}, {109, 248, 149, 29}, {109, 248, 149, 30}}},
|
||||||
|
{Region: "Latvia", Group: "Premium TCP Europe", IPs: []net.IP{{109, 248, 148, 243}, {109, 248, 148, 244}, {109, 248, 148, 252}, {109, 248, 149, 19}, {109, 248, 149, 23}, {109, 248, 149, 25}, {109, 248, 149, 27}, {109, 248, 149, 28}, {109, 248, 149, 29}, {109, 248, 149, 30}}},
|
||||||
|
{Region: "Liechtenstein", Group: "Premium TCP Europe", IPs: []net.IP{{91, 90, 122, 131}, {91, 90, 122, 133}, {91, 90, 122, 134}, {91, 90, 122, 135}, {91, 90, 122, 136}, {91, 90, 122, 137}, {91, 90, 122, 142}, {91, 90, 122, 143}, {91, 90, 122, 144}, {91, 90, 122, 145}}},
|
||||||
|
{Region: "Liechtenstein", Group: "Premium UDP Europe", IPs: []net.IP{{91, 90, 122, 131}, {91, 90, 122, 132}, {91, 90, 122, 134}, {91, 90, 122, 136}, {91, 90, 122, 138}, {91, 90, 122, 141}, {91, 90, 122, 142}, {91, 90, 122, 143}, {91, 90, 122, 144}, {91, 90, 122, 145}}},
|
||||||
|
{Region: "Lithuania", Group: "Premium TCP Europe", IPs: []net.IP{{85, 206, 162, 209}, {85, 206, 162, 211}, {85, 206, 162, 216}, {85, 206, 162, 217}, {85, 206, 162, 218}, {85, 206, 162, 221}, {85, 206, 165, 25}, {85, 206, 165, 26}, {85, 206, 165, 30}, {85, 206, 165, 31}}},
|
||||||
|
{Region: "Lithuania", Group: "Premium UDP Europe", IPs: []net.IP{{85, 206, 162, 209}, {85, 206, 162, 211}, {85, 206, 162, 216}, {85, 206, 162, 217}, {85, 206, 162, 219}, {85, 206, 162, 221}, {85, 206, 165, 19}, {85, 206, 165, 20}, {85, 206, 165, 23}, {85, 206, 165, 30}}},
|
||||||
|
{Region: "Luxembourg", Group: "Premium UDP Europe", IPs: []net.IP{{5, 253, 204, 19}, {5, 253, 204, 20}, {5, 253, 204, 22}, {5, 253, 204, 23}, {5, 253, 204, 24}, {5, 253, 204, 27}, {5, 253, 204, 29}, {5, 253, 204, 35}, {5, 253, 204, 44}, {5, 253, 204, 45}}},
|
||||||
|
{Region: "Luxembourg", Group: "Premium TCP Europe", IPs: []net.IP{{5, 253, 204, 9}, {5, 253, 204, 10}, {5, 253, 204, 24}, {5, 253, 204, 28}, {5, 253, 204, 30}, {5, 253, 204, 35}, {5, 253, 204, 38}, {5, 253, 204, 39}, {5, 253, 204, 41}, {5, 253, 204, 46}}},
|
||||||
|
{Region: "Macao", Group: "Premium TCP Asia", IPs: []net.IP{{84, 252, 92, 131}, {84, 252, 92, 133}, {84, 252, 92, 134}, {84, 252, 92, 135}, {84, 252, 92, 136}, {84, 252, 92, 139}, {84, 252, 92, 141}, {84, 252, 92, 143}, {84, 252, 92, 144}, {84, 252, 92, 145}}},
|
||||||
|
{Region: "Macao", Group: "Premium UDP Asia", IPs: []net.IP{{84, 252, 92, 131}, {84, 252, 92, 132}, {84, 252, 92, 133}, {84, 252, 92, 138}, {84, 252, 92, 140}, {84, 252, 92, 141}, {84, 252, 92, 142}, {84, 252, 92, 143}, {84, 252, 92, 144}, {84, 252, 92, 145}}},
|
||||||
|
{Region: "Macedonia", Group: "Premium UDP Europe", IPs: []net.IP{{185, 225, 28, 3}, {185, 225, 28, 4}, {185, 225, 28, 5}, {185, 225, 28, 6}, {185, 225, 28, 7}, {185, 225, 28, 8}, {185, 225, 28, 9}, {185, 225, 28, 10}, {185, 225, 28, 11}, {185, 225, 28, 12}}},
|
||||||
|
{Region: "Macedonia", Group: "Premium TCP Europe", IPs: []net.IP{{185, 225, 28, 3}, {185, 225, 28, 4}, {185, 225, 28, 5}, {185, 225, 28, 6}, {185, 225, 28, 7}, {185, 225, 28, 8}, {185, 225, 28, 9}, {185, 225, 28, 10}, {185, 225, 28, 11}, {185, 225, 28, 12}}},
|
||||||
|
{Region: "Malaysia", Group: "Premium TCP Asia", IPs: []net.IP{{139, 5, 177, 69}, {139, 5, 177, 70}, {139, 5, 177, 71}, {139, 5, 177, 72}, {139, 5, 177, 73}, {139, 5, 177, 74}, {139, 5, 177, 75}, {139, 5, 177, 76}, {139, 5, 177, 77}, {139, 5, 177, 78}}},
|
||||||
|
{Region: "Malaysia", Group: "Premium UDP Asia", IPs: []net.IP{{139, 5, 177, 69}, {139, 5, 177, 70}, {139, 5, 177, 71}, {139, 5, 177, 72}, {139, 5, 177, 73}, {139, 5, 177, 74}, {139, 5, 177, 75}, {139, 5, 177, 76}, {139, 5, 177, 77}, {139, 5, 177, 78}}},
|
||||||
|
{Region: "Malta", Group: "Premium UDP Europe", IPs: []net.IP{{176, 125, 230, 131}, {176, 125, 230, 132}, {176, 125, 230, 133}, {176, 125, 230, 135}, {176, 125, 230, 136}, {176, 125, 230, 140}, {176, 125, 230, 141}, {176, 125, 230, 142}, {176, 125, 230, 143}, {176, 125, 230, 145}}},
|
||||||
|
{Region: "Malta", Group: "Premium TCP Europe", IPs: []net.IP{{176, 125, 230, 132}, {176, 125, 230, 133}, {176, 125, 230, 134}, {176, 125, 230, 135}, {176, 125, 230, 136}, {176, 125, 230, 138}, {176, 125, 230, 140}, {176, 125, 230, 142}, {176, 125, 230, 143}, {176, 125, 230, 144}}},
|
||||||
|
{Region: "Mexico", Group: "Premium UDP USA", IPs: []net.IP{{77, 81, 142, 132}, {77, 81, 142, 136}, {77, 81, 142, 137}, {77, 81, 142, 139}, {77, 81, 142, 140}, {77, 81, 142, 143}, {77, 81, 142, 146}, {77, 81, 142, 149}, {77, 81, 142, 154}, {77, 81, 142, 155}}},
|
||||||
|
{Region: "Mexico", Group: "Premium TCP USA", IPs: []net.IP{{77, 81, 142, 130}, {77, 81, 142, 132}, {77, 81, 142, 134}, {77, 81, 142, 136}, {77, 81, 142, 138}, {77, 81, 142, 142}, {77, 81, 142, 146}, {77, 81, 142, 150}, {77, 81, 142, 154}, {77, 81, 142, 155}}},
|
||||||
|
{Region: "Moldova", Group: "Premium UDP Europe", IPs: []net.IP{{178, 175, 130, 243}, {178, 175, 130, 244}, {178, 175, 130, 245}, {178, 175, 130, 246}, {178, 175, 130, 250}, {178, 175, 130, 251}, {178, 175, 130, 252}, {178, 175, 130, 254}, {178, 175, 142, 133}, {178, 175, 142, 134}}},
|
||||||
|
{Region: "Moldova", Group: "Premium TCP Europe", IPs: []net.IP{{178, 175, 130, 243}, {178, 175, 130, 244}, {178, 175, 130, 245}, {178, 175, 130, 246}, {178, 175, 130, 250}, {178, 175, 130, 252}, {178, 175, 130, 253}, {178, 175, 130, 254}, {178, 175, 142, 132}, {178, 175, 142, 134}}},
|
||||||
|
{Region: "Monaco", Group: "Premium UDP Europe", IPs: []net.IP{{95, 181, 233, 131}, {95, 181, 233, 134}, {95, 181, 233, 135}, {95, 181, 233, 136}, {95, 181, 233, 137}, {95, 181, 233, 138}, {95, 181, 233, 140}, {95, 181, 233, 141}, {95, 181, 233, 142}, {95, 181, 233, 143}}},
|
||||||
|
{Region: "Monaco", Group: "Premium TCP Europe", IPs: []net.IP{{95, 181, 233, 131}, {95, 181, 233, 132}, {95, 181, 233, 134}, {95, 181, 233, 136}, {95, 181, 233, 137}, {95, 181, 233, 140}, {95, 181, 233, 141}, {95, 181, 233, 142}, {95, 181, 233, 143}, {95, 181, 233, 144}}},
|
||||||
|
{Region: "Mongolia", Group: "Premium TCP Asia", IPs: []net.IP{{185, 253, 163, 132}, {185, 253, 163, 134}, {185, 253, 163, 136}, {185, 253, 163, 137}, {185, 253, 163, 138}, {185, 253, 163, 139}, {185, 253, 163, 140}, {185, 253, 163, 142}, {185, 253, 163, 144}, {185, 253, 163, 145}}},
|
||||||
|
{Region: "Mongolia", Group: "Premium UDP Asia", IPs: []net.IP{{185, 253, 163, 131}, {185, 253, 163, 134}, {185, 253, 163, 136}, {185, 253, 163, 137}, {185, 253, 163, 139}, {185, 253, 163, 140}, {185, 253, 163, 141}, {185, 253, 163, 142}, {185, 253, 163, 144}, {185, 253, 163, 145}}},
|
||||||
|
{Region: "Montenegro", Group: "Premium UDP Europe", IPs: []net.IP{{176, 125, 229, 132}, {176, 125, 229, 133}, {176, 125, 229, 134}, {176, 125, 229, 135}, {176, 125, 229, 137}, {176, 125, 229, 139}, {176, 125, 229, 140}, {176, 125, 229, 141}, {176, 125, 229, 142}, {176, 125, 229, 145}}},
|
||||||
|
{Region: "Montenegro", Group: "Premium TCP Europe", IPs: []net.IP{{176, 125, 229, 131}, {176, 125, 229, 134}, {176, 125, 229, 135}, {176, 125, 229, 137}, {176, 125, 229, 138}, {176, 125, 229, 140}, {176, 125, 229, 141}, {176, 125, 229, 142}, {176, 125, 229, 143}, {176, 125, 229, 145}}},
|
||||||
|
{Region: "Morocco", Group: "Premium UDP Europe", IPs: []net.IP{{95, 181, 232, 131}, {95, 181, 232, 132}, {95, 181, 232, 134}, {95, 181, 232, 135}, {95, 181, 232, 139}, {95, 181, 232, 140}, {95, 181, 232, 141}, {95, 181, 232, 142}, {95, 181, 232, 143}, {95, 181, 232, 144}}},
|
||||||
|
{Region: "Morocco", Group: "Premium TCP Europe", IPs: []net.IP{{95, 181, 232, 131}, {95, 181, 232, 133}, {95, 181, 232, 134}, {95, 181, 232, 135}, {95, 181, 232, 137}, {95, 181, 232, 138}, {95, 181, 232, 139}, {95, 181, 232, 141}, {95, 181, 232, 142}, {95, 181, 232, 143}}},
|
||||||
|
{Region: "Netherlands", Group: "Premium TCP Europe", IPs: []net.IP{{84, 17, 47, 2}, {84, 17, 47, 3}, {84, 17, 47, 9}, {84, 17, 47, 15}, {84, 17, 47, 16}, {84, 17, 47, 54}, {84, 17, 47, 69}, {84, 17, 47, 81}, {84, 17, 47, 111}, {195, 181, 172, 72}}},
|
||||||
|
{Region: "Netherlands", Group: "Premium UDP Europe", IPs: []net.IP{{84, 17, 47, 9}, {84, 17, 47, 34}, {84, 17, 47, 52}, {84, 17, 47, 53}, {84, 17, 47, 66}, {84, 17, 47, 73}, {84, 17, 47, 95}, {139, 28, 217, 222}, {195, 181, 172, 67}, {195, 181, 172, 68}}},
|
||||||
|
{Region: "New Zealand", Group: "Premium TCP Asia", IPs: []net.IP{{114, 141, 194, 2}, {114, 141, 194, 3}, {114, 141, 194, 4}, {114, 141, 194, 5}, {114, 141, 194, 7}, {114, 141, 194, 8}, {114, 141, 194, 10}, {114, 141, 194, 12}, {114, 141, 194, 13}, {114, 141, 194, 14}}},
|
||||||
|
{Region: "New Zealand", Group: "Premium UDP Asia", IPs: []net.IP{{114, 141, 194, 2}, {114, 141, 194, 3}, {114, 141, 194, 5}, {114, 141, 194, 6}, {114, 141, 194, 7}, {114, 141, 194, 8}, {114, 141, 194, 9}, {114, 141, 194, 11}, {114, 141, 194, 12}, {114, 141, 194, 13}}},
|
||||||
|
{Region: "Nigeria", Group: "Premium TCP Europe", IPs: []net.IP{{102, 165, 25, 68}, {102, 165, 25, 69}, {102, 165, 25, 70}, {102, 165, 25, 71}, {102, 165, 25, 72}, {102, 165, 25, 73}, {102, 165, 25, 74}, {102, 165, 25, 76}, {102, 165, 25, 77}, {102, 165, 25, 78}}},
|
||||||
|
{Region: "Nigeria", Group: "Premium UDP Europe", IPs: []net.IP{{102, 165, 25, 68}, {102, 165, 25, 69}, {102, 165, 25, 70}, {102, 165, 25, 71}, {102, 165, 25, 72}, {102, 165, 25, 74}, {102, 165, 25, 75}, {102, 165, 25, 76}, {102, 165, 25, 77}, {102, 165, 25, 78}}},
|
||||||
|
{Region: "Norway", Group: "Premium UDP Europe", IPs: []net.IP{{45, 12, 223, 137}, {45, 12, 223, 140}, {45, 12, 223, 141}, {82, 102, 27, 92}, {185, 206, 225, 29}, {185, 206, 225, 231}, {185, 206, 225, 235}, {185, 253, 97, 248}, {185, 253, 97, 249}, {185, 253, 97, 250}}},
|
||||||
|
{Region: "Norway", Group: "Premium TCP Europe", IPs: []net.IP{{185, 206, 225, 229}, {185, 206, 225, 230}, {185, 206, 225, 231}, {185, 206, 225, 232}, {185, 206, 225, 234}, {185, 253, 97, 236}, {185, 253, 97, 243}, {185, 253, 97, 245}, {185, 253, 97, 247}, {185, 253, 97, 251}}},
|
||||||
|
{Region: "Pakistan", Group: "Premium TCP Europe", IPs: []net.IP{{103, 76, 3, 244}, {103, 76, 3, 245}, {103, 76, 3, 246}, {103, 76, 3, 247}, {103, 76, 3, 248}, {103, 76, 3, 249}, {103, 76, 3, 250}, {103, 76, 3, 251}, {103, 76, 3, 252}, {103, 76, 3, 253}}},
|
||||||
|
{Region: "Pakistan", Group: "Premium UDP Europe", IPs: []net.IP{{103, 76, 3, 244}, {103, 76, 3, 245}, {103, 76, 3, 246}, {103, 76, 3, 247}, {103, 76, 3, 248}, {103, 76, 3, 249}, {103, 76, 3, 250}, {103, 76, 3, 251}, {103, 76, 3, 252}, {103, 76, 3, 253}}},
|
||||||
|
{Region: "Panama", Group: "Premium UDP Europe", IPs: []net.IP{{91, 90, 126, 131}, {91, 90, 126, 132}, {91, 90, 126, 133}, {91, 90, 126, 134}, {91, 90, 126, 135}, {91, 90, 126, 136}, {91, 90, 126, 139}, {91, 90, 126, 141}, {91, 90, 126, 143}, {91, 90, 126, 144}}},
|
||||||
|
{Region: "Panama", Group: "Premium TCP Europe", IPs: []net.IP{{91, 90, 126, 131}, {91, 90, 126, 132}, {91, 90, 126, 134}, {91, 90, 126, 135}, {91, 90, 126, 137}, {91, 90, 126, 139}, {91, 90, 126, 140}, {91, 90, 126, 142}, {91, 90, 126, 144}, {91, 90, 126, 145}}},
|
||||||
|
{Region: "Philippines", Group: "Premium UDP Asia", IPs: []net.IP{{188, 214, 125, 35}, {188, 214, 125, 36}, {188, 214, 125, 41}, {188, 214, 125, 44}, {188, 214, 125, 47}, {188, 214, 125, 52}, {188, 214, 125, 53}, {188, 214, 125, 54}, {188, 214, 125, 55}, {188, 214, 125, 60}}},
|
||||||
|
{Region: "Philippines", Group: "Premium TCP Asia", IPs: []net.IP{{188, 214, 125, 36}, {188, 214, 125, 37}, {188, 214, 125, 39}, {188, 214, 125, 43}, {188, 214, 125, 45}, {188, 214, 125, 47}, {188, 214, 125, 48}, {188, 214, 125, 57}, {188, 214, 125, 58}, {188, 214, 125, 59}}},
|
||||||
|
{Region: "Poland", Group: "Premium TCP Europe", IPs: []net.IP{{37, 120, 156, 5}, {37, 120, 156, 9}, {37, 120, 156, 19}, {37, 120, 156, 27}, {37, 120, 156, 29}, {37, 120, 156, 35}, {37, 120, 156, 36}, {51, 75, 56, 40}, {51, 75, 56, 41}, {51, 75, 56, 44}}},
|
||||||
|
{Region: "Poland", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 156, 4}, {37, 120, 156, 10}, {37, 120, 156, 16}, {37, 120, 156, 23}, {37, 120, 156, 27}, {37, 120, 156, 29}, {37, 120, 156, 30}, {37, 120, 156, 38}, {37, 120, 156, 39}, {51, 75, 56, 36}}},
|
||||||
|
{Region: "Portugal", Group: "Premium TCP Europe", IPs: []net.IP{{89, 26, 243, 1}, {89, 26, 243, 98}, {89, 26, 243, 112}, {89, 26, 243, 113}, {89, 26, 243, 115}, {89, 26, 243, 195}, {89, 26, 243, 196}, {89, 26, 243, 197}, {89, 26, 243, 198}, {89, 26, 243, 199}}},
|
||||||
|
{Region: "Portugal", Group: "Premium UDP Europe", IPs: []net.IP{{89, 26, 243, 1}, {89, 26, 243, 99}, {89, 26, 243, 113}, {89, 26, 243, 115}, {89, 26, 243, 194}, {89, 26, 243, 195}, {89, 26, 243, 196}, {89, 26, 243, 197}, {89, 26, 243, 198}, {89, 26, 243, 199}}},
|
||||||
|
{Region: "Qatar", Group: "Premium TCP Europe", IPs: []net.IP{{95, 181, 234, 132}, {95, 181, 234, 133}, {95, 181, 234, 134}, {95, 181, 234, 136}, {95, 181, 234, 138}, {95, 181, 234, 140}, {95, 181, 234, 141}, {95, 181, 234, 142}, {95, 181, 234, 143}, {95, 181, 234, 144}}},
|
||||||
|
{Region: "Qatar", Group: "Premium UDP Europe", IPs: []net.IP{{95, 181, 234, 131}, {95, 181, 234, 132}, {95, 181, 234, 133}, {95, 181, 234, 134}, {95, 181, 234, 137}, {95, 181, 234, 138}, {95, 181, 234, 141}, {95, 181, 234, 142}, {95, 181, 234, 143}, {95, 181, 234, 144}}},
|
||||||
|
{Region: "Russian Federation", Group: "Premium TCP Europe", IPs: []net.IP{{5, 8, 16, 67}, {5, 8, 16, 71}, {5, 8, 16, 73}, {5, 8, 16, 75}, {5, 8, 16, 76}, {5, 8, 16, 87}, {5, 8, 16, 88}, {5, 8, 16, 89}, {5, 8, 16, 90}, {5, 8, 16, 104}}},
|
||||||
|
{Region: "Russian Federation", Group: "Premium UDP Europe", IPs: []net.IP{{5, 8, 16, 68}, {5, 8, 16, 75}, {5, 8, 16, 84}, {5, 8, 16, 86}, {5, 8, 16, 87}, {5, 8, 16, 88}, {5, 8, 16, 104}, {5, 8, 16, 106}, {5, 8, 16, 107}, {5, 8, 16, 110}}},
|
||||||
|
{Region: "Saudi Arabia", Group: "Premium UDP Europe", IPs: []net.IP{{95, 181, 235, 132}, {95, 181, 235, 133}, {95, 181, 235, 134}, {95, 181, 235, 135}, {95, 181, 235, 136}, {95, 181, 235, 137}, {95, 181, 235, 139}, {95, 181, 235, 141}, {95, 181, 235, 142}, {95, 181, 235, 143}}},
|
||||||
|
{Region: "Saudi Arabia", Group: "Premium TCP Europe", IPs: []net.IP{{95, 181, 235, 134}, {95, 181, 235, 136}, {95, 181, 235, 137}, {95, 181, 235, 138}, {95, 181, 235, 139}, {95, 181, 235, 140}, {95, 181, 235, 141}, {95, 181, 235, 142}, {95, 181, 235, 143}, {95, 181, 235, 144}}},
|
||||||
|
{Region: "Serbia", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 193, 182}, {37, 120, 193, 185}, {37, 120, 193, 187}, {141, 98, 103, 35}, {141, 98, 103, 37}, {141, 98, 103, 39}, {141, 98, 103, 41}, {141, 98, 103, 42}, {141, 98, 103, 44}, {141, 98, 103, 46}}},
|
||||||
|
{Region: "Serbia", Group: "Premium TCP Europe", IPs: []net.IP{{37, 120, 193, 180}, {37, 120, 193, 182}, {37, 120, 193, 183}, {37, 120, 193, 184}, {37, 120, 193, 190}, {141, 98, 103, 35}, {141, 98, 103, 36}, {141, 98, 103, 39}, {141, 98, 103, 40}, {141, 98, 103, 42}}},
|
||||||
|
{Region: "Singapore", Group: "Premium TCP Asia", IPs: []net.IP{{37, 120, 151, 59}, {37, 120, 151, 134}, {37, 120, 151, 135}, {37, 120, 151, 136}, {37, 120, 151, 140}, {37, 120, 151, 141}, {84, 17, 39, 172}, {84, 17, 39, 173}, {84, 17, 39, 178}, {84, 17, 39, 179}}},
|
||||||
|
{Region: "Singapore", Group: "Premium UDP Asia", IPs: []net.IP{{37, 120, 151, 52}, {37, 120, 151, 133}, {37, 120, 151, 138}, {37, 120, 151, 140}, {37, 120, 151, 142}, {84, 17, 39, 171}, {84, 17, 39, 176}, {84, 17, 39, 177}, {84, 17, 39, 179}, {84, 17, 39, 182}}},
|
||||||
|
{Region: "Slovakia", Group: "Premium TCP Europe", IPs: []net.IP{{185, 245, 85, 227}, {185, 245, 85, 228}, {185, 245, 85, 229}, {185, 245, 85, 230}, {185, 245, 85, 231}, {185, 245, 85, 232}, {185, 245, 85, 233}, {185, 245, 85, 234}, {185, 245, 85, 235}, {185, 245, 85, 236}}},
|
||||||
|
{Region: "Slovakia", Group: "Premium UDP Europe", IPs: []net.IP{{185, 245, 85, 227}, {185, 245, 85, 228}, {185, 245, 85, 229}, {185, 245, 85, 230}, {185, 245, 85, 231}, {185, 245, 85, 232}, {185, 245, 85, 233}, {185, 245, 85, 234}, {185, 245, 85, 235}, {185, 245, 85, 236}}},
|
||||||
|
{Region: "Slovenia", Group: "Premium TCP Europe", IPs: []net.IP{{146, 247, 25, 79}, {146, 247, 25, 80}, {146, 247, 25, 81}, {146, 247, 25, 82}, {146, 247, 25, 83}, {146, 247, 25, 84}, {146, 247, 25, 85}, {146, 247, 25, 86}, {146, 247, 25, 88}, {146, 247, 25, 89}}},
|
||||||
|
{Region: "Slovenia", Group: "Premium UDP Europe", IPs: []net.IP{{146, 247, 25, 79}, {146, 247, 25, 80}, {146, 247, 25, 81}, {146, 247, 25, 82}, {146, 247, 25, 83}, {146, 247, 25, 84}, {146, 247, 25, 86}, {146, 247, 25, 88}, {146, 247, 25, 89}, {146, 247, 25, 90}}},
|
||||||
|
{Region: "South Africa", Group: "Premium UDP Europe", IPs: []net.IP{{197, 85, 7, 26}, {197, 85, 7, 27}, {197, 85, 7, 28}, {197, 85, 7, 29}, {197, 85, 7, 30}, {197, 85, 7, 31}, {197, 85, 7, 131}, {197, 85, 7, 132}, {197, 85, 7, 133}, {197, 85, 7, 134}}},
|
||||||
|
{Region: "South Africa", Group: "Premium UDP Asia", IPs: []net.IP{{165, 73, 248, 211}, {165, 73, 248, 213}, {165, 73, 248, 215}, {165, 73, 248, 219}, {165, 73, 248, 221}, {165, 73, 248, 228}, {165, 73, 248, 231}, {165, 73, 248, 232}, {165, 73, 248, 235}, {165, 73, 248, 237}}},
|
||||||
|
{Region: "South Africa", Group: "Premium TCP Europe", IPs: []net.IP{{197, 85, 7, 26}, {197, 85, 7, 27}, {197, 85, 7, 28}, {197, 85, 7, 29}, {197, 85, 7, 30}, {197, 85, 7, 31}, {197, 85, 7, 131}, {197, 85, 7, 132}, {197, 85, 7, 133}, {197, 85, 7, 134}}},
|
||||||
|
{Region: "South Africa", Group: "Premium TCP Asia", IPs: []net.IP{{165, 73, 248, 214}, {165, 73, 248, 215}, {165, 73, 248, 216}, {165, 73, 248, 218}, {165, 73, 248, 219}, {165, 73, 248, 221}, {165, 73, 248, 229}, {165, 73, 248, 235}, {165, 73, 248, 236}, {165, 73, 248, 238}}},
|
||||||
|
{Region: "Spain", Group: "Premium TCP Europe", IPs: []net.IP{{82, 102, 26, 204}, {82, 102, 26, 205}, {84, 17, 62, 130}, {84, 17, 62, 131}, {84, 17, 62, 140}, {84, 17, 62, 147}, {185, 93, 3, 109}, {185, 93, 3, 110}, {185, 93, 3, 112}, {185, 253, 99, 205}}},
|
||||||
|
{Region: "Spain", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 142, 54}, {37, 120, 142, 55}, {37, 120, 142, 58}, {37, 120, 142, 150}, {82, 102, 26, 196}, {82, 102, 26, 218}, {84, 17, 62, 138}, {185, 93, 3, 106}, {185, 93, 182, 139}, {185, 253, 99, 202}}},
|
||||||
|
{Region: "Sri Lanka", Group: "Premium UDP Europe", IPs: []net.IP{{95, 181, 239, 131}, {95, 181, 239, 134}, {95, 181, 239, 136}, {95, 181, 239, 137}, {95, 181, 239, 138}, {95, 181, 239, 139}, {95, 181, 239, 140}, {95, 181, 239, 141}, {95, 181, 239, 142}, {95, 181, 239, 143}}},
|
||||||
|
{Region: "Sri Lanka", Group: "Premium TCP Europe", IPs: []net.IP{{95, 181, 239, 131}, {95, 181, 239, 133}, {95, 181, 239, 134}, {95, 181, 239, 135}, {95, 181, 239, 136}, {95, 181, 239, 137}, {95, 181, 239, 140}, {95, 181, 239, 141}, {95, 181, 239, 143}, {95, 181, 239, 144}}},
|
||||||
|
{Region: "Sweden", Group: "Premium UDP Europe", IPs: []net.IP{{188, 126, 73, 202}, {188, 126, 73, 209}, {188, 126, 73, 215}, {188, 126, 73, 221}, {195, 246, 120, 150}, {195, 246, 120, 156}, {195, 246, 120, 160}, {195, 246, 120, 169}, {195, 246, 120, 170}, {195, 246, 120, 173}}},
|
||||||
|
{Region: "Sweden", Group: "Premium TCP Europe", IPs: []net.IP{{188, 126, 73, 204}, {188, 126, 73, 214}, {188, 126, 73, 218}, {188, 126, 73, 221}, {195, 246, 120, 145}, {195, 246, 120, 149}, {195, 246, 120, 151}, {195, 246, 120, 154}, {195, 246, 120, 171}, {195, 246, 120, 179}}},
|
||||||
|
{Region: "Switzerland", Group: "Premium TCP Europe", IPs: []net.IP{{84, 17, 52, 11}, {84, 17, 52, 12}, {84, 17, 52, 22}, {84, 17, 52, 49}, {84, 17, 52, 55}, {84, 17, 52, 62}, {84, 17, 52, 85}, {185, 32, 222, 13}, {185, 189, 150, 61}, {185, 189, 150, 73}}},
|
||||||
|
{Region: "Switzerland", Group: "Premium UDP Europe", IPs: []net.IP{{84, 17, 52, 20}, {84, 17, 52, 33}, {84, 17, 52, 38}, {84, 17, 52, 51}, {84, 17, 52, 69}, {84, 17, 52, 74}, {185, 32, 222, 16}, {185, 32, 222, 118}, {185, 32, 222, 120}, {195, 225, 118, 52}}},
|
||||||
|
{Region: "Taiwan", Group: "Premium TCP Asia", IPs: []net.IP{{45, 133, 181, 102}, {45, 133, 181, 103}, {45, 133, 181, 106}, {45, 133, 181, 108}, {45, 133, 181, 109}, {45, 133, 181, 110}, {45, 133, 181, 112}, {45, 133, 181, 116}, {45, 133, 181, 120}, {45, 133, 181, 123}}},
|
||||||
|
{Region: "Taiwan", Group: "Premium UDP Asia", IPs: []net.IP{{45, 133, 181, 99}, {45, 133, 181, 101}, {45, 133, 181, 105}, {45, 133, 181, 110}, {45, 133, 181, 111}, {45, 133, 181, 114}, {45, 133, 181, 116}, {45, 133, 181, 117}, {45, 133, 181, 121}, {45, 133, 181, 123}}},
|
||||||
|
{Region: "Thailand", Group: "Premium UDP Asia", IPs: []net.IP{{119, 59, 121, 163}, {119, 59, 121, 165}, {119, 59, 121, 166}, {119, 59, 121, 167}, {119, 59, 121, 168}, {119, 59, 121, 169}, {119, 59, 121, 170}, {119, 59, 121, 172}, {119, 59, 121, 173}, {119, 59, 121, 175}}},
|
||||||
|
{Region: "Thailand", Group: "Premium TCP Asia", IPs: []net.IP{{119, 59, 98, 213}, {119, 59, 98, 244}, {119, 59, 121, 163}, {119, 59, 121, 164}, {119, 59, 121, 166}, {119, 59, 121, 169}, {119, 59, 121, 170}, {119, 59, 121, 171}, {119, 59, 121, 172}, {119, 59, 121, 175}}},
|
||||||
|
{Region: "Turkey", Group: "Premium TCP Europe", IPs: []net.IP{{188, 213, 34, 3}, {188, 213, 34, 6}, {188, 213, 34, 10}, {188, 213, 34, 19}, {188, 213, 34, 24}, {188, 213, 34, 28}, {188, 213, 34, 37}, {188, 213, 34, 43}, {188, 213, 34, 104}, {188, 213, 34, 109}}},
|
||||||
|
{Region: "Turkey", Group: "Premium UDP Europe", IPs: []net.IP{{188, 213, 34, 14}, {188, 213, 34, 22}, {188, 213, 34, 26}, {188, 213, 34, 27}, {188, 213, 34, 30}, {188, 213, 34, 39}, {188, 213, 34, 42}, {188, 213, 34, 43}, {188, 213, 34, 100}, {188, 213, 34, 106}}},
|
||||||
|
{Region: "Ukraine", Group: "Premium TCP Europe", IPs: []net.IP{{31, 28, 161, 21}, {31, 28, 163, 40}, {31, 28, 163, 43}, {31, 28, 163, 50}, {62, 149, 7, 165}, {62, 149, 7, 166}, {62, 149, 7, 173}, {62, 149, 29, 36}, {62, 149, 29, 48}, {62, 149, 29, 56}}},
|
||||||
|
{Region: "Ukraine", Group: "Premium UDP Europe", IPs: []net.IP{{31, 28, 161, 20}, {31, 28, 163, 35}, {31, 28, 163, 40}, {31, 28, 163, 42}, {31, 28, 163, 52}, {31, 28, 163, 55}, {62, 149, 7, 172}, {62, 149, 7, 173}, {62, 149, 29, 37}, {62, 149, 29, 58}}},
|
||||||
|
{Region: "United Arab Emirates", Group: "Premium TCP Europe", IPs: []net.IP{{217, 138, 193, 179}, {217, 138, 193, 180}, {217, 138, 193, 182}, {217, 138, 193, 184}, {217, 138, 193, 185}, {217, 138, 193, 186}, {217, 138, 193, 187}, {217, 138, 193, 188}, {217, 138, 193, 189}, {217, 138, 193, 190}}},
|
||||||
|
{Region: "United Arab Emirates", Group: "Premium UDP Europe", IPs: []net.IP{{217, 138, 193, 179}, {217, 138, 193, 180}, {217, 138, 193, 182}, {217, 138, 193, 183}, {217, 138, 193, 184}, {217, 138, 193, 185}, {217, 138, 193, 186}, {217, 138, 193, 187}, {217, 138, 193, 188}, {217, 138, 193, 189}}},
|
||||||
|
{Region: "United Kingdom", Group: "Premium UDP Europe", IPs: []net.IP{{37, 120, 159, 101}, {37, 235, 96, 9}, {81, 92, 206, 164}, {81, 92, 206, 169}, {84, 17, 51, 97}, {84, 17, 51, 123}, {89, 238, 167, 85}, {89, 238, 167, 91}, {109, 169, 14, 97}, {141, 98, 100, 73}}},
|
||||||
|
{Region: "United Kingdom", Group: "Premium TCP Europe", IPs: []net.IP{{37, 120, 133, 165}, {37, 120, 159, 81}, {37, 235, 96, 9}, {84, 17, 51, 44}, {84, 17, 51, 107}, {89, 238, 167, 39}, {89, 238, 167, 54}, {143, 244, 39, 135}, {143, 244, 39, 221}, {143, 244, 39, 232}}},
|
||||||
|
{Region: "United States", Group: "Premium UDP USA", IPs: []net.IP{{23, 105, 161, 116}, {143, 244, 51, 84}, {156, 146, 37, 43}, {156, 146, 37, 73}, {156, 146, 37, 100}, {156, 146, 37, 103}, {156, 146, 51, 20}, {156, 146, 51, 103}, {156, 146, 51, 128}, {156, 146, 59, 172}}},
|
||||||
|
{Region: "United States", Group: "Premium TCP USA", IPs: []net.IP{{89, 187, 171, 139}, {89, 187, 171, 161}, {89, 187, 182, 38}, {143, 244, 51, 111}, {156, 146, 37, 101}, {156, 146, 37, 123}, {156, 146, 49, 133}, {156, 146, 51, 103}, {156, 146, 51, 146}, {185, 242, 5, 115}}},
|
||||||
|
{Region: "Venezuela", Group: "Premium TCP USA", IPs: []net.IP{{95, 181, 237, 131}, {95, 181, 237, 134}, {95, 181, 237, 136}, {95, 181, 237, 137}, {95, 181, 237, 138}, {95, 181, 237, 139}, {95, 181, 237, 140}, {95, 181, 237, 141}, {95, 181, 237, 142}, {95, 181, 237, 143}}},
|
||||||
|
{Region: "Venezuela", Group: "Premium UDP USA", IPs: []net.IP{{95, 181, 237, 131}, {95, 181, 237, 132}, {95, 181, 237, 135}, {95, 181, 237, 136}, {95, 181, 237, 137}, {95, 181, 237, 138}, {95, 181, 237, 140}, {95, 181, 237, 142}, {95, 181, 237, 143}, {95, 181, 237, 144}}},
|
||||||
|
{Region: "Vietnam", Group: "Premium TCP Asia", IPs: []net.IP{{188, 214, 152, 99}, {188, 214, 152, 100}, {188, 214, 152, 101}, {188, 214, 152, 102}, {188, 214, 152, 103}, {188, 214, 152, 105}, {188, 214, 152, 106}, {188, 214, 152, 107}, {188, 214, 152, 108}, {188, 214, 152, 110}}},
|
||||||
|
{Region: "Vietnam", Group: "Premium UDP Asia", IPs: []net.IP{{188, 214, 152, 99}, {188, 214, 152, 100}, {188, 214, 152, 102}, {188, 214, 152, 103}, {188, 214, 152, 104}, {188, 214, 152, 105}, {188, 214, 152, 106}, {188, 214, 152, 108}, {188, 214, 152, 109}, {188, 214, 152, 110}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
package constants
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Cloudflare is a DNS over TLS provider
|
|
||||||
Cloudflare models.DNSProvider = "cloudflare"
|
|
||||||
// Google is a DNS over TLS provider
|
|
||||||
Google models.DNSProvider = "google"
|
|
||||||
// Quad9 is a DNS over TLS provider
|
|
||||||
Quad9 models.DNSProvider = "quad9"
|
|
||||||
// Quadrant is a DNS over TLS provider
|
|
||||||
Quadrant models.DNSProvider = "quadrant"
|
|
||||||
// CleanBrowsing is a DNS over TLS provider
|
|
||||||
CleanBrowsing models.DNSProvider = "cleanbrowsing"
|
|
||||||
// SecureDNS is a DNS over TLS provider
|
|
||||||
SecureDNS models.DNSProvider = "securedns"
|
|
||||||
// LibreDNS is a DNS over TLS provider
|
|
||||||
LibreDNS models.DNSProvider = "libredns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DNSProviderMapping returns a constant mapping of dns provider name
|
|
||||||
// to their data such as IP addresses or TLS host name.
|
|
||||||
func DNSProviderMapping() map[models.DNSProvider]models.DNSProviderData {
|
|
||||||
return map[models.DNSProvider]models.DNSProviderData{
|
|
||||||
Cloudflare: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{1, 1, 1, 1}, {1, 0, 0, 1}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("cloudflare-dns.com"),
|
|
||||||
},
|
|
||||||
Google: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{8, 8, 8, 8}, {8, 8, 4, 4}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("dns.google"),
|
|
||||||
},
|
|
||||||
Quad9: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{9, 9, 9, 9}, {149, 112, 112, 112}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("dns.quad9.net"),
|
|
||||||
},
|
|
||||||
Quadrant: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{12, 159, 2, 159}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("dns-tls.qis.io"),
|
|
||||||
},
|
|
||||||
CleanBrowsing: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{185, 228, 168, 9}, {185, 228, 169, 9}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("security-filter-dns.cleanbrowsing.org"),
|
|
||||||
},
|
|
||||||
SecureDNS: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{146, 185, 167, 43}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("dot.securedns.eu"),
|
|
||||||
},
|
|
||||||
LibreDNS: models.DNSProviderData{
|
|
||||||
IPs: []net.IP{{116, 203, 115, 192}},
|
|
||||||
SupportsTLS: true,
|
|
||||||
Host: models.DNSHost("dot.libredns.gr"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block lists URLs
|
|
||||||
const (
|
|
||||||
AdsBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/ads-hostnames.updated"
|
|
||||||
AdsBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/ads-ips.updated"
|
|
||||||
MaliciousBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/malicious-hostnames.updated"
|
|
||||||
MaliciousBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/malicious-ips.updated"
|
|
||||||
SurveillanceBlockListHostnamesURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/surveillance-hostnames.updated"
|
|
||||||
SurveillanceBlockListIPsURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/surveillance-ips.updated"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DNS certificates to fetch
|
|
||||||
// TODO obtain from source directly, see qdm12/updated)
|
|
||||||
const (
|
|
||||||
NamedRootURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/named.root.updated"
|
|
||||||
RootKeyURL models.URL = "https://raw.githubusercontent.com/qdm12/files/master/root.key.updated"
|
|
||||||
)
|
|
||||||
142
internal/constants/mullvad.go
Normal file
142
internal/constants/mullvad.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
MullvadCertificate = "MIIGIzCCBAugAwIBAgIJAK6BqXN9GHI0MA0GCSqGSIb3DQEBCwUAMIGfMQswCQYDVQQGEwJTRTERMA8GA1UECAwIR290YWxhbmQxEzARBgNVBAcMCkdvdGhlbmJ1cmcxFDASBgNVBAoMC0FtYWdpY29tIEFCMRAwDgYDVQQLDAdNdWxsdmFkMRswGQYDVQQDDBJNdWxsdmFkIFJvb3QgQ0EgdjIxIzAhBgkqhkiG9w0BCQEWFHNlY3VyaXR5QG11bGx2YWQubmV0MB4XDTE4MTEwMjExMTYxMVoXDTI4MTAzMDExMTYxMVowgZ8xCzAJBgNVBAYTAlNFMREwDwYDVQQIDAhHb3RhbGFuZDETMBEGA1UEBwwKR290aGVuYnVyZzEUMBIGA1UECgwLQW1hZ2ljb20gQUIxEDAOBgNVBAsMB011bGx2YWQxGzAZBgNVBAMMEk11bGx2YWQgUm9vdCBDQSB2MjEjMCEGCSqGSIb3DQEJARYUc2VjdXJpdHlAbXVsbHZhZC5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCifDn75E/Zdx1qsy31rMEzuvbTXqZVZp4bjWbmcyyXqvnayRUHHoovG+lzc+HDL3HJV+kjxKpCMkEVWwjY159lJbQbm8kkYntBBREdzRRjjJpTb6haf/NXeOtQJ9aVlCc4dM66bEmyAoXkzXVZTQJ8h2FE55KVxHi5Sdy4XC5zm0wPa4DPDokNp1qm3A9Xicq3HsflLbMZRCAGuI+Jek6caHqiKjTHtujn6Gfxv2WsZ7SjerUAk+mvBo2sfKmB7octxG7yAOFFg7YsWL0AxddBWqgq5R/1WDJ9d1Cwun9WGRRQ1TLvzF1yABUerjjKrk89RCzYISwsKcgJPscaDqZgO6RIruY/xjuTtrnZSv+FXs+Woxf87P+QgQd76LC0MstTnys+AfTMuMPOLy9fMfEzs3LP0Nz6v5yjhX8ff7+3UUI3IcMxCvyxdTPClY5IvFdW7CCmmLNzakmx5GCItBWg/EIg1K1SG0jU9F8vlNZUqLKz42hWy/xB5C4QYQQ9ILdu4araPnrXnmd1D1QKVwKQ1DpWhNbpBDfE776/4xXD/tGM5O0TImp1NXul8wYsDi8g+e0pxNgY3Pahnj1yfG75Yw82spZanUH0QSNoMVMWnmV2hXGsWqypRq0pH8mPeLzeKa82gzsAZsouRD1k8wFlYA4z9HQFxqfcntTqXuwQcQIDAQABo2AwXjAdBgNVHQ4EFgQUfaEyaBpGNzsqttiSMETq+X/GJ0YwHwYDVR0jBBgwFoAUfaEyaBpGNzsqttiSMETq+X/GJ0YwCwYDVR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBADH5izxu4V8Javal8EA4DxZxIHUsWCg5cuopB28PsyJYpyKipsBoI8+RXqbtrLLue4WQfNPZHLXlKi+A3GTrLdlnenYzXVipPd+n3vRZyofaB3Jtb03nirVWGa8FG21Xy/f4rPqwcW54lxrnnh0SA0hwuZ+b2yAWESBXPxrzVQdTWCqoFI6/aRnN8RyZn0LqRYoW7WDtKpLmfyvshBmmu4PCYSh/SYiFHgR9fsWzVcxdySDsmX8wXowuFfp8V9sFhD4TsebAaplaICOuLUgj+Yin5QzgB0F9Ci3Zh6oWwl64SL/OxxQLpzMWzr0lrWsQrS3PgC4+6JC4IpTXX5eUqfSvHPtbRKK0yLnd9hYgvZUBvvZvUFR/3/fW+mpBHbZJBu9+/1uux46M4rJ2FeaJUf9PhYCPuUj63yu0Grn0DreVKK1SkD5V6qXN0TmoxYyguhfsIPCpI1VsdaSWuNjJ+a/HIlKIU8vKp5iN/+6ZTPAg9Q7s3Ji+vfx/AhFtQyTpIYNszVzNZyobvkiMUlK+eUKGlHVQp73y6MmGIlbBbyzpEoedNU4uFu57mw4fYGHqYZmYqFaiNQv4tVrGkg6p+Ypyu1zOfIHF7eqlAOu/SyRTvZkt9VtSVEOVH7nDIGdrCC9U/g1Lqk8Td00Oj8xesyKzsG214Xd8m7/7GmJ7nXe5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MullvadCountryChoices() (choices []string) {
|
||||||
|
uniqueChoices := map[string]struct{}{}
|
||||||
|
for _, server := range MullvadServers() {
|
||||||
|
uniqueChoices[server.Country] = struct{}{}
|
||||||
|
}
|
||||||
|
for choice := range uniqueChoices {
|
||||||
|
choices = append(choices, choice)
|
||||||
|
}
|
||||||
|
sort.Slice(choices, func(i, j int) bool {
|
||||||
|
return choices[i] < choices[j]
|
||||||
|
})
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func MullvadCityChoices() (choices []string) {
|
||||||
|
uniqueChoices := map[string]struct{}{}
|
||||||
|
for _, server := range MullvadServers() {
|
||||||
|
uniqueChoices[server.City] = struct{}{}
|
||||||
|
}
|
||||||
|
for choice := range uniqueChoices {
|
||||||
|
choices = append(choices, choice)
|
||||||
|
}
|
||||||
|
sort.Slice(choices, func(i, j int) bool {
|
||||||
|
return choices[i] < choices[j]
|
||||||
|
})
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func MullvadISPChoices() (choices []string) {
|
||||||
|
uniqueChoices := map[string]struct{}{}
|
||||||
|
for _, server := range MullvadServers() {
|
||||||
|
uniqueChoices[server.ISP] = struct{}{}
|
||||||
|
}
|
||||||
|
for choice := range uniqueChoices {
|
||||||
|
choices = append(choices, choice)
|
||||||
|
}
|
||||||
|
sort.Slice(choices, func(i, j int) bool {
|
||||||
|
return choices[i] < choices[j]
|
||||||
|
})
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:dupl,lll
|
||||||
|
// MullvadServers returns a slice of all the server information for Mullvad.
|
||||||
|
func MullvadServers() []models.MullvadServer {
|
||||||
|
return []models.MullvadServer{
|
||||||
|
{Country: "Albania", City: "Tirana", ISP: "iRegister", Owned: false, IPs: []net.IP{{31, 171, 154, 210}}, IPsV6: []net.IP{{0x2a, 0x4, 0x27, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Australia", City: "Adelaide", ISP: "Intergrid", Owned: false, IPs: []net.IP{{116, 206, 231, 58}}, IPsV6: []net.IP{{0x24, 0x7, 0xa0, 0x80, 0x50, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Australia", City: "Brisbane", ISP: "Intergrid", Owned: false, IPs: []net.IP{{43, 245, 160, 162}}, IPsV6: []net.IP{{0x24, 0x7, 0xa0, 0x80, 0x20, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Australia", City: "Canberra", ISP: "Intergrid", Owned: false, IPs: []net.IP{{116, 206, 229, 98}}, IPsV6: []net.IP{{0x24, 0x7, 0xa0, 0x80, 0x40, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Australia", City: "Melbourne", ISP: "Intergrid", Owned: false, IPs: []net.IP{{116, 206, 228, 202}, {116, 206, 228, 242}, {116, 206, 230, 98}}, IPsV6: []net.IP{{0x24, 0x7, 0xa0, 0x80, 0x30, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x24, 0x7, 0xa0, 0x80, 0x30, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x24, 0x7, 0xa0, 0x80, 0x30, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "Australia", City: "Perth", ISP: "Intergrid", Owned: false, IPs: []net.IP{{103, 77, 235, 66}}, IPsV6: []net.IP{{0x24, 0x0, 0xfa, 0x80, 0x0, 0x5, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Australia", City: "Sydney", ISP: "Intergrid", Owned: false, IPs: []net.IP{{43, 245, 162, 130}, {103, 77, 232, 130}, {103, 77, 232, 146}}, IPsV6: []net.IP{{0x24, 0x0, 0xfa, 0x80, 0x0, 0x1, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x24, 0x0, 0xfa, 0x80, 0x0, 0x1, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x24, 0x0, 0xfa, 0x80, 0x0, 0x1, 0x0, 0x15, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Australia", City: "Sydney", ISP: "M247", Owned: false, IPs: []net.IP{{89, 44, 10, 18}, {89, 44, 10, 34}, {89, 44, 10, 50}, {89, 44, 10, 194}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x84, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x84, 0x0, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x84, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x84, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "Austria", City: "Vienna", ISP: "M247", Owned: false, IPs: []net.IP{{5, 253, 207, 34}, {86, 107, 21, 210}, {86, 107, 21, 226}, {86, 107, 21, 242}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x29, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x29, 0x0, 0x5a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x29, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x29, 0x0, 0x5c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x4f}}},
|
||||||
|
{Country: "Belgium", City: "Brussels", ISP: "M247", Owned: false, IPs: []net.IP{{37, 120, 143, 138}, {37, 120, 218, 138}, {37, 120, 218, 146}, {91, 207, 57, 50}, {185, 104, 186, 202}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x27, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x27, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x27, 0x0, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x27, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x27, 0x0, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}}},
|
||||||
|
{Country: "Brazil", City: "Sao Paulo", ISP: "Heficed", Owned: false, IPs: []net.IP{{191, 101, 62, 178}}, IPsV6: []net.IP{{0x28, 0x3, 0x0, 0x80, 0x80, 0x3, 0x80, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Brazil", City: "Sao Paulo", ISP: "Qnax", Owned: false, IPs: []net.IP{{177, 67, 80, 186}}, IPsV6: []net.IP{{0x28, 0x4, 0x53, 0x64, 0x21, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Bulgaria", City: "Sofia", ISP: "M247", Owned: false, IPs: []net.IP{{37, 120, 152, 114}, {37, 120, 152, 146}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x30, 0x0, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x30, 0x0, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Canada", City: "Montreal", ISP: "M247", Owned: false, IPs: []net.IP{{89, 36, 78, 18}, {89, 36, 78, 34}, {89, 36, 78, 50}, {89, 36, 78, 66}, {89, 36, 78, 82}, {89, 36, 78, 98}, {89, 36, 78, 114}, {89, 36, 78, 130}}, IPsV6: []net.IP{{0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x0, 0xc9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x9, 0x1, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}}},
|
||||||
|
{Country: "Canada", City: "Toronto", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 132, 34}, {198, 54, 132, 50}, {198, 54, 132, 66}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x60, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x26, 0x7, 0x90, 0x0, 0x60, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x60, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}}},
|
||||||
|
{Country: "Canada", City: "Vancouver", ISP: "100TB", Owned: false, IPs: []net.IP{{172, 83, 40, 38}}, IPsV6: []net.IP{{0x26, 0x7, 0xf7, 0xa0, 0x0, 0xd, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Canada", City: "Vancouver", ISP: "Esecuredata", Owned: false, IPs: []net.IP{{71, 19, 248, 240}, {71, 19, 249, 81}}, IPsV6: []net.IP{{0x26, 0x5, 0x0, 0x80, 0x0, 0x18, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}, {0x26, 0x5, 0x0, 0x80, 0x0, 0x19, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5}}},
|
||||||
|
{Country: "Czech Republic", City: "Prague", ISP: "M247", Owned: false, IPs: []net.IP{{185, 156, 174, 146}, {185, 156, 174, 170}, {185, 216, 35, 242}, {217, 138, 199, 74}, {217, 138, 199, 82}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x33, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x33, 0x0, 0xb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x33, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x33, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x33, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}}},
|
||||||
|
{Country: "Denmark", City: "Copenhagen", ISP: "31173", Owned: true, IPs: []net.IP{{45, 129, 56, 81}, {141, 98, 254, 71}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x8, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x8, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Denmark", City: "Copenhagen", ISP: "Asergo", Owned: false, IPs: []net.IP{{82, 103, 140, 213}}, IPsV6: []net.IP{{0x2a, 0x0, 0x90, 0x80, 0x0, 0x1, 0x9, 0x8c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Denmark", City: "Copenhagen", ISP: "Blix", Owned: false, IPs: []net.IP{{134, 90, 149, 138}}, IPsV6: []net.IP{{0x2a, 0x2, 0xed, 0x1, 0x41, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Denmark", City: "Copenhagen", ISP: "M247", Owned: false, IPs: []net.IP{{89, 45, 7, 130}, {89, 45, 7, 146}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x37, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x37, 0x0, 0x5c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x4f}}},
|
||||||
|
{Country: "Finland", City: "Helsinki", ISP: "Creanova", Owned: true, IPs: []net.IP{{185, 204, 1, 171}, {185, 204, 1, 172}, {185, 204, 1, 173}, {185, 204, 1, 174}, {185, 204, 1, 175}, {185, 204, 1, 176}, {185, 212, 149, 201}}, IPsV6: []net.IP{{0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0xc, 0xf0, 0x40, 0x0, 0x0, 0x27, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}}},
|
||||||
|
{Country: "France", City: "Paris", ISP: "31173", Owned: true, IPs: []net.IP{{193, 32, 126, 81}, {193, 32, 126, 82}, {193, 32, 126, 83}, {193, 32, 126, 84}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x9, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x9, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x9, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x9, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "France", City: "Paris", ISP: "M247", Owned: false, IPs: []net.IP{{89, 44, 9, 19}, {89, 44, 9, 35}, {194, 110, 113, 3}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x25, 0x0, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x25, 0x0, 0xd1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x25, 0x0, 0xd2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}}},
|
||||||
|
{Country: "Germany", City: "Frankfurt", ISP: "31173", Owned: true, IPs: []net.IP{{185, 213, 155, 131}, {185, 213, 155, 132}, {185, 213, 155, 133}, {185, 213, 155, 134}, {185, 213, 155, 135}, {185, 213, 155, 136}, {185, 213, 155, 137}, {185, 213, 155, 138}, {185, 213, 155, 139}, {185, 213, 155, 140}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x6, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}}},
|
||||||
|
{Country: "Germany", City: "Frankfurt", ISP: "M247", Owned: false, IPs: []net.IP{{193, 27, 14, 2}, {193, 27, 14, 18}, {193, 27, 14, 34}, {193, 27, 14, 50}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x20, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x20, 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x20, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x20, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x4f}}},
|
||||||
|
{Country: "Greece", City: "Athens", ISP: "aweb", Owned: false, IPs: []net.IP{{185, 226, 67, 168}}, IPsV6: []net.IP{{0x2a, 0xc, 0x5e, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Hong Kong", City: "Hong Kong", ISP: "Leaseweb", Owned: false, IPs: []net.IP{{209, 58, 184, 146}, {209, 58, 185, 53}, {209, 58, 185, 186}}, IPsV6: []net.IP{{0x20, 0x1, 0xd, 0xf1, 0x8, 0x1, 0xa0, 0x3, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xd, 0xf1, 0x8, 0x1, 0xa0, 0x3, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xd, 0xf1, 0x8, 0x1, 0xa0, 0x5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Hong Kong", City: "Hong Kong", ISP: "M247", Owned: false, IPs: []net.IP{{89, 45, 6, 50}, {89, 45, 6, 66}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x92, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x92, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Hungary", City: "Budapest", ISP: "M247", Owned: false, IPs: []net.IP{{86, 106, 74, 34}, {86, 106, 74, 50}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x26, 0x0, 0xab, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x26, 0x0, 0xac, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "Ireland", City: "Dublin", ISP: "M247", Owned: false, IPs: []net.IP{{217, 138, 222, 82}, {217, 138, 222, 90}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x88, 0x0, 0x5a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x88, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Israel", City: "Tel Aviv", ISP: "HQServ", Owned: false, IPs: []net.IP{{185, 191, 207, 210}}, IPsV6: []net.IP{{0x2a, 0xa, 0x1d, 0xc4, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Italy", City: "Milan", ISP: "M247", Owned: false, IPs: []net.IP{{89, 40, 182, 146}, {89, 40, 182, 210}, {192, 145, 127, 98}, {192, 145, 127, 114}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x24, 0x0, 0x76, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x24, 0x0, 0x77, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x24, 0x0, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x24, 0x0, 0x79, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "Japan", City: "Tokyo", ISP: "M247", Owned: false, IPs: []net.IP{{217, 138, 252, 50}, {217, 138, 252, 162}, {217, 138, 252, 178}, {217, 138, 252, 194}, {217, 138, 252, 210}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x40, 0x0, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x40, 0x0, 0xb2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x40, 0x0, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x40, 0x0, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x40, 0x0, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}}},
|
||||||
|
{Country: "Latvia", City: "Riga", ISP: "Makonix", Owned: false, IPs: []net.IP{{31, 170, 22, 2}}, IPsV6: []net.IP{{0x2a, 0x0, 0xc, 0x68, 0x0, 0x0, 0xcb, 0xcf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Luxembourg", City: "Luxembourg", ISP: "Evoluso", Owned: false, IPs: []net.IP{{92, 223, 89, 160}, {92, 223, 89, 182}}, IPsV6: []net.IP{{0x2a, 0x3, 0x90, 0xc0, 0x0, 0x83, 0x29, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x90, 0xc0, 0x0, 0x83, 0x29, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Moldova", City: "Chisinau", ISP: "Trabia", Owned: false, IPs: []net.IP{{178, 175, 142, 194}}, IPsV6: []net.IP{{0x2a, 0x0, 0x1d, 0xc0, 0x29, 0x25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Netherlands", City: "Amsterdam", ISP: "31173", Owned: true, IPs: []net.IP{{185, 65, 134, 131}, {185, 65, 134, 132}, {185, 65, 134, 133}, {185, 65, 134, 134}, {185, 65, 134, 135}, {185, 65, 134, 136}, {185, 65, 134, 139}, {185, 65, 134, 140}, {185, 65, 134, 141}, {185, 65, 134, 142}, {185, 65, 134, 143}, {185, 65, 134, 144}, {185, 65, 134, 145}, {185, 65, 134, 146}, {185, 65, 134, 147}, {185, 65, 134, 148}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x3, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8f}}},
|
||||||
|
{Country: "New Zealand", City: "Auckland", ISP: "Intergrid", Owned: false, IPs: []net.IP{{103, 231, 91, 114}}, IPsV6: []net.IP{{0x24, 0x0, 0xfa, 0x80, 0x0, 0x4, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Norway", City: "Oslo", ISP: "Blix", Owned: true, IPs: []net.IP{{91, 90, 44, 11}, {91, 90, 44, 12}, {91, 90, 44, 13}, {91, 90, 44, 14}, {91, 90, 44, 15}, {91, 90, 44, 16}, {91, 90, 44, 17}, {91, 90, 44, 18}}, IPsV6: []net.IP{{0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0x2, 0x20, 0xc8, 0x41, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}}},
|
||||||
|
{Country: "Poland", City: "Warsaw", ISP: "M247", Owned: false, IPs: []net.IP{{37, 120, 156, 162}, {37, 120, 211, 186}, {37, 120, 211, 194}, {37, 120, 211, 202}, {185, 244, 214, 210}, {185, 244, 214, 215}}, IPsV6: []net.IP{{0x2a, 0xd, 0x56, 0x0, 0x0, 0x13, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x13, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x13, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x13, 0x0, 0x3a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x13, 0x0, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x13, 0xb, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Romania", City: "Bucharest", ISP: "M247", Owned: false, IPs: []net.IP{{185, 163, 110, 66}, {185, 163, 110, 98}}, IPsV6: []net.IP{{0x2a, 0x4, 0x9d, 0xc0, 0x0, 0x0, 0x0, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1f}, {0x2a, 0x4, 0x9d, 0xc0, 0x0, 0x0, 0x0, 0x92, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x3f}}},
|
||||||
|
{Country: "Serbia", City: "Belgrade", ISP: "M247", Owned: false, IPs: []net.IP{{89, 38, 224, 98}, {89, 38, 224, 114}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x7d, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x7d, 0x0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}}},
|
||||||
|
{Country: "Serbia", City: "Nis", ISP: "ninet", Owned: false, IPs: []net.IP{{176, 104, 107, 118}}, IPsV6: []net.IP{{0x2a, 0x6, 0x1, 0x85, 0x0, 0x1, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Singapore", City: "Singapore", ISP: "M247", Owned: false, IPs: []net.IP{{89, 38, 225, 34}, {94, 198, 43, 2}, {94, 198, 43, 18}}, IPsV6: []net.IP{{0x2a, 0xa, 0xb6, 0x40, 0x0, 0x1, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0xa, 0xb6, 0x40, 0x0, 0x1, 0x0, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xa, 0xb6, 0x40, 0x0, 0x1, 0x0, 0x56, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Spain", City: "Madrid", ISP: "M247", Owned: false, IPs: []net.IP{{45, 152, 183, 26}, {45, 152, 183, 42}, {89, 238, 178, 34}, {89, 238, 178, 74}, {195, 206, 107, 146}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x23, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x23, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf2}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x23, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x23, 0x0, 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x23, 0x0, 0x59, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}}},
|
||||||
|
{Country: "Sweden", City: "Gothenburg", ISP: "31173", Owned: true, IPs: []net.IP{{185, 213, 154, 131}, {185, 213, 154, 132}, {185, 213, 154, 133}, {185, 213, 154, 134}, {185, 213, 154, 135}, {185, 213, 154, 136}, {185, 213, 154, 137}, {185, 213, 154, 138}, {185, 213, 154, 139}, {185, 213, 154, 140}, {185, 213, 154, 141}, {185, 213, 154, 142}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x5, 0xf0, 0x11, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}}},
|
||||||
|
{Country: "Sweden", City: "Helsingborg", ISP: "31173", Owned: true, IPs: []net.IP{{185, 213, 152, 131}, {185, 213, 152, 132}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x2, 0xf7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x2, 0xf7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "Sweden", City: "Malmö", ISP: "31173", Owned: true, IPs: []net.IP{{45, 83, 220, 87}, {45, 83, 220, 88}, {45, 83, 220, 89}, {45, 83, 220, 90}, {45, 83, 220, 91}, {45, 83, 220, 92}, {45, 83, 220, 93}, {141, 98, 255, 83}, {141, 98, 255, 84}, {141, 98, 255, 85}, {141, 98, 255, 86}, {141, 98, 255, 87}, {141, 98, 255, 88}, {141, 98, 255, 89}, {141, 98, 255, 90}, {141, 98, 255, 91}, {141, 98, 255, 92}, {141, 98, 255, 93}, {141, 98, 255, 94}, {193, 138, 218, 132}, {193, 138, 218, 133}, {193, 138, 218, 134}, {193, 138, 218, 135}, {193, 138, 218, 136}, {193, 138, 218, 137}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xe0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xf}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x1, 0xf4, 0x10, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}}},
|
||||||
|
{Country: "Sweden", City: "Stockholm", ISP: "31173", Owned: true, IPs: []net.IP{{185, 65, 135, 136}, {185, 65, 135, 137}, {185, 65, 135, 138}, {185, 65, 135, 139}, {185, 65, 135, 140}, {185, 65, 135, 141}, {185, 65, 135, 142}, {185, 65, 135, 143}, {185, 65, 135, 144}, {185, 65, 135, 145}, {185, 65, 135, 146}, {185, 65, 135, 147}, {185, 65, 135, 148}, {185, 65, 135, 149}, {185, 65, 135, 150}, {185, 65, 135, 151}, {185, 65, 135, 152}, {185, 65, 135, 153}, {185, 65, 135, 154}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4e}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xf}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x4, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x4f}}},
|
||||||
|
{Country: "Switzerland", City: "Zurich", ISP: "31173", Owned: true, IPs: []net.IP{{193, 32, 127, 81}, {193, 32, 127, 82}, {193, 32, 127, 83}, {193, 32, 127, 84}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0xa, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0xa, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0xa, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0xa, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "Switzerland", City: "Zurich", ISP: "M247", Owned: false, IPs: []net.IP{{91, 193, 4, 2}, {91, 193, 4, 18}, {91, 193, 4, 34}, {91, 193, 4, 50}, {91, 193, 4, 66}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x28, 0x0, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x28, 0x0, 0x85, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x28, 0x0, 0x86, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x28, 0x0, 0x87, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x28, 0x0, 0x97, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "Switzerland", City: "Zurich", ISP: "PrivateLayer", Owned: false, IPs: []net.IP{{81, 17, 20, 34}, {179, 43, 128, 170}}, IPsV6: []net.IP{{0x2a, 0x2, 0x29, 0xb8, 0xdc, 0x1, 0x5, 0x97, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x2, 0x29, 0xb8, 0xdc, 0x1, 0x18, 0x81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "UK", City: "London", ISP: "31173", Owned: true, IPs: []net.IP{{141, 98, 252, 131}, {141, 98, 252, 132}, {141, 98, 252, 133}, {141, 98, 252, 138}, {141, 98, 252, 139}, {141, 98, 252, 140}, {185, 195, 232, 84}, {185, 195, 232, 85}, {185, 195, 232, 86}}, IPsV6: []net.IP{{0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0x3, 0x1b, 0x20, 0x0, 0x7, 0xf0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}}},
|
||||||
|
{Country: "UK", City: "London", ISP: "M247", Owned: false, IPs: []net.IP{{45, 87, 215, 50}, {185, 200, 118, 178}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x31, 0x2, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x31, 0x2, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "UK", City: "Manchester", ISP: "M247", Owned: false, IPs: []net.IP{{37, 120, 159, 164}, {89, 238, 132, 36}, {194, 37, 96, 180}, {217, 151, 98, 68}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x21, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x21, 0x0, 0x1b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x21, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x21, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "USA", City: "Atlanta GA", ISP: "100TB", Owned: false, IPs: []net.IP{{66, 115, 180, 227}, {66, 115, 180, 228}, {66, 115, 180, 229}, {66, 115, 180, 230}, {107, 152, 108, 62}}, IPsV6: []net.IP{{0x26, 0x7, 0xf7, 0xa0, 0x0, 0x1, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0x1, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0x1, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0x1, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0x6, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}}},
|
||||||
|
{Country: "USA", City: "Atlanta GA", ISP: "Quadranet", Owned: false, IPs: []net.IP{{104, 129, 24, 242}}, IPsV6: []net.IP{{0x26, 0x7, 0xfc, 0xd0, 0xaa, 0x80, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "USA", City: "Chicago IL", ISP: "Quadranet", Owned: false, IPs: []net.IP{{104, 129, 31, 26}}, IPsV6: []net.IP{{0x26, 0x7, 0xfc, 0xd0, 0xbb, 0x80, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "USA", City: "Chicago IL", ISP: "Tzulo", Owned: false, IPs: []net.IP{{68, 235, 43, 10}, {68, 235, 43, 18}, {68, 235, 43, 26}, {68, 235, 43, 34}, {68, 235, 43, 42}, {68, 235, 43, 50}, {68, 235, 43, 58}, {68, 235, 43, 66}, {68, 235, 43, 74}, {68, 235, 43, 122}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x56, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x57, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}, {0x26, 0x7, 0x90, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "USA", City: "Dallas TX", ISP: "100TB", Owned: false, IPs: []net.IP{{174, 127, 113, 3}, {174, 127, 113, 4}, {174, 127, 113, 5}, {174, 127, 113, 6}, {174, 127, 113, 7}}, IPsV6: []net.IP{{0x26, 0x6, 0x2e, 0x0, 0x80, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x26, 0x6, 0x2e, 0x0, 0x80, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x6, 0x2e, 0x0, 0x80, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x26, 0x6, 0x2e, 0x0, 0x80, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x26, 0x6, 0x2e, 0x0, 0x80, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}}},
|
||||||
|
{Country: "USA", City: "Dallas TX", ISP: "M247", Owned: false, IPs: []net.IP{{193, 27, 13, 34}, {193, 27, 13, 50}, {193, 27, 13, 66}, {193, 27, 13, 82}, {193, 27, 13, 178}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x9a, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x9a, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x9a, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x9a, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x20, 0x1, 0xa, 0xc8, 0x0, 0x9a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "USA", City: "Dallas TX", ISP: "Quadranet", Owned: false, IPs: []net.IP{{96, 44, 145, 18}, {96, 44, 147, 130}}, IPsV6: []net.IP{{0x26, 0x7, 0xfc, 0xd0, 0xda, 0x80, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8}, {0x26, 0x7, 0xfc, 0xd0, 0xda, 0x80, 0x18, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9}}},
|
||||||
|
{Country: "USA", City: "Denver CO", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 128, 66}, {198, 54, 128, 74}, {198, 54, 128, 106}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x20, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x20, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x26, 0x7, 0x90, 0x0, 0x20, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}}},
|
||||||
|
{Country: "USA", City: "Los Angeles CA", ISP: "100TB", Owned: false, IPs: []net.IP{{104, 200, 152, 66}, {107, 181, 168, 130}}, IPsV6: []net.IP{{0x26, 0x7, 0xf7, 0xa0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}}},
|
||||||
|
{Country: "USA", City: "Los Angeles CA", ISP: "M247", Owned: false, IPs: []net.IP{{89, 46, 114, 15}, {89, 46, 114, 28}, {89, 46, 114, 41}, {89, 46, 114, 54}, {89, 46, 114, 67}, {89, 46, 114, 80}, {89, 46, 114, 93}, {89, 46, 114, 106}, {89, 46, 114, 119}, {89, 46, 114, 132}, {89, 46, 114, 145}, {89, 46, 114, 158}, {89, 46, 114, 171}, {89, 46, 114, 184}, {89, 46, 114, 197}, {89, 46, 114, 210}}, IPsV6: []net.IP{{0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6f}}},
|
||||||
|
{Country: "USA", City: "Los Angeles CA", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 129, 74}, {198, 54, 129, 82}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x30, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "USA", City: "Miami FL", ISP: "M247", Owned: false, IPs: []net.IP{{94, 198, 42, 50}, {94, 198, 42, 66}, {94, 198, 42, 82}, {94, 198, 42, 98}, {193, 27, 12, 2}, {193, 27, 12, 18}}, IPsV6: []net.IP{{0x2a, 0xd, 0x56, 0x0, 0x0, 0x6, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x6, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x6, 0x0, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x6, 0x0, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x6, 0xa, 0xd6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x6, 0xa, 0xd7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
{Country: "USA", City: "New York NY", ISP: "100TB", Owned: false, IPs: []net.IP{{107, 182, 226, 206}, {107, 182, 226, 218}}, IPsV6: []net.IP{{0x26, 0x6, 0x2e, 0x0, 0x80, 0x3, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x26, 0x6, 0x2e, 0x0, 0x80, 0x3, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}}},
|
||||||
|
{Country: "USA", City: "New York NY", ISP: "M247", Owned: false, IPs: []net.IP{{86, 106, 121, 15}, {86, 106, 121, 28}, {86, 106, 121, 41}, {86, 106, 121, 54}, {86, 106, 121, 67}, {86, 106, 121, 80}, {86, 106, 121, 93}, {86, 106, 121, 106}, {86, 106, 121, 119}, {89, 46, 62, 15}, {89, 46, 62, 28}, {89, 46, 62, 41}, {89, 46, 62, 54}, {89, 46, 62, 67}, {89, 46, 62, 80}, {89, 46, 62, 93}, {89, 46, 62, 106}, {89, 46, 62, 119}}, IPsV6: []net.IP{{0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x73, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x74, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x75, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x76, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x77, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x79, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x9a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x9b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x9c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x9d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x9e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0x9f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0xa1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8f}, {0x2a, 0xd, 0x56, 0x0, 0x0, 0x24, 0xa, 0xa2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x9f}}},
|
||||||
|
{Country: "USA", City: "Phoenix AZ", ISP: "100TB", Owned: false, IPs: []net.IP{{107, 152, 99, 86}}, IPsV6: []net.IP{{0x26, 0x7, 0xf7, 0xa0, 0x0, 0x5, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}}},
|
||||||
|
{Country: "USA", City: "Phoenix AZ", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 133, 34}, {198, 54, 133, 50}, {198, 54, 133, 66}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x70, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1f}, {0x26, 0x7, 0x90, 0x0, 0x70, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x70, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x3f}}},
|
||||||
|
{Country: "USA", City: "Raleigh NC", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 130, 34}, {198, 54, 130, 50}, {198, 54, 130, 66}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x40, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1f}, {0x26, 0x7, 0x90, 0x0, 0x40, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x40, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x3f}}},
|
||||||
|
{Country: "USA", City: "Salt Lake City UT", ISP: "100TB", Owned: false, IPs: []net.IP{{69, 4, 234, 132}, {69, 4, 234, 133}, {69, 4, 234, 134}, {69, 4, 234, 135}, {69, 4, 234, 136}, {69, 4, 234, 137}}, IPsV6: []net.IP{{0x26, 0x6, 0x2e, 0x0, 0x0, 0x0, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x26, 0x6, 0x2e, 0x0, 0x0, 0x0, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x6, 0x2e, 0x0, 0x0, 0x0, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x26, 0x6, 0x2e, 0x0, 0x0, 0x0, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f}, {0x26, 0x6, 0x2e, 0x0, 0x0, 0x0, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f}, {0x26, 0x6, 0x2e, 0x0, 0x0, 0x0, 0x0, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f}}},
|
||||||
|
{Country: "USA", City: "San Jose CA", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 134, 34}, {198, 54, 134, 50}, {198, 54, 134, 66}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x80, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x26, 0x7, 0x90, 0x0, 0x80, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x80, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}}},
|
||||||
|
{Country: "USA", City: "Seattle WA", ISP: "100TB", Owned: false, IPs: []net.IP{{104, 200, 129, 42}, {104, 200, 129, 110}, {104, 200, 129, 150}}, IPsV6: []net.IP{{0x26, 0x7, 0xf7, 0xa0, 0x0, 0xc, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0xc, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f}, {0x26, 0x7, 0xf7, 0xa0, 0x0, 0xc, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "USA", City: "Seattle WA", ISP: "Tzulo", Owned: false, IPs: []net.IP{{198, 54, 131, 34}, {198, 54, 131, 50}, {198, 54, 131, 66}}, IPsV6: []net.IP{{0x26, 0x7, 0x90, 0x0, 0x50, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1f}, {0x26, 0x7, 0x90, 0x0, 0x50, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x2f}, {0x26, 0x7, 0x90, 0x0, 0x50, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x3f}}},
|
||||||
|
{Country: "USA", City: "Secaucus NJ", ISP: "Quadranet", Owned: false, IPs: []net.IP{{23, 226, 131, 130}, {23, 226, 131, 154}}, IPsV6: []net.IP{{0x26, 0x7, 0xfc, 0xd0, 0xcc, 0xc0, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}, {0x26, 0x7, 0xfc, 0xd0, 0xcc, 0xc0, 0x1d, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f}}},
|
||||||
|
{Country: "United Arab Emirates", City: "Dubai", ISP: "M247", Owned: false, IPs: []net.IP{{45, 9, 249, 34}}, IPsV6: []net.IP{{0x20, 0x1, 0xa, 0xc8, 0x0, 0x81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
5366
internal/constants/nordvpn.go
Normal file
5366
internal/constants/nordvpn.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,6 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TUN models.VPNDevice = "tun0"
|
TUN = "tun0"
|
||||||
TAP models.VPNDevice = "tap0"
|
TAP = "tap0"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
import (
|
const (
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
// UnboundConf is the file path to the Unbound configuration file.
|
||||||
)
|
UnboundConf string = "/etc/unbound/unbound.conf"
|
||||||
|
// ResolvConf is the file path to the system resolv.conf file.
|
||||||
const (
|
ResolvConf string = "/etc/resolv.conf"
|
||||||
// UnboundConf is the file path to the Unbound configuration file
|
// CACertificates is the file path to the CA certificates file.
|
||||||
UnboundConf models.Filepath = "/etc/unbound/unbound.conf"
|
CACertificates string = "/etc/ssl/certs/ca-certificates.crt"
|
||||||
// ResolvConf is the file path to the system resolv.conf file
|
// OpenVPNAuthConf is the file path to the OpenVPN auth file.
|
||||||
ResolvConf models.Filepath = "/etc/resolv.conf"
|
OpenVPNAuthConf string = "/etc/openvpn/auth.conf"
|
||||||
// CACertificates is the file path to the CA certificates file
|
// OpenVPNConf is the file path to the OpenVPN client configuration file.
|
||||||
CACertificates models.Filepath = "/etc/ssl/certs/ca-certificates.crt"
|
OpenVPNConf string = "/etc/openvpn/target.ovpn"
|
||||||
// OpenVPNAuthConf is the file path to the OpenVPN auth file
|
// PIAPortForward is the file path to the port forwarding JSON information for PIA servers.
|
||||||
OpenVPNAuthConf models.Filepath = "/etc/openvpn/auth.conf"
|
PIAPortForward string = "/gluetun/piaportforward.json"
|
||||||
// OpenVPNConf is the file path to the OpenVPN client configuration file
|
// TunnelDevice is the file path to tun device.
|
||||||
OpenVPNConf models.Filepath = "/etc/openvpn/target.ovpn"
|
TunnelDevice string = "/dev/net/tun"
|
||||||
// TunnelDevice is the file path to tun device
|
// NetRoute is the path to the file containing information on the network route.
|
||||||
TunnelDevice models.Filepath = "/dev/net/tun"
|
NetRoute string = "/proc/net/route"
|
||||||
// NetRoute is the path to the file containing information on the network route
|
// RootHints is the filepath to the root.hints file used by Unbound.
|
||||||
NetRoute models.Filepath = "/proc/net/route"
|
RootHints string = "/etc/unbound/root.hints"
|
||||||
// TinyProxyConf is the filepath to the tinyproxy configuration file
|
// RootKey is the filepath to the root.key file used by Unbound.
|
||||||
TinyProxyConf models.Filepath = "/etc/tinyproxy/tinyproxy.conf"
|
RootKey string = "/etc/unbound/root.key"
|
||||||
// ShadowsocksConf is the filepath to the shadowsocks configuration file
|
// Client key filepath, used by Cyberghost.
|
||||||
ShadowsocksConf models.Filepath = "/etc/shadowsocks.json"
|
ClientKey string = "/gluetun/client.key"
|
||||||
// RootHints is the filepath to the root.hints file used by Unbound
|
// Client certificate filepath, used by Cyberghost.
|
||||||
RootHints models.Filepath = "/etc/unbound/root.hints"
|
ClientCertificate string = "/gluetun/client.crt"
|
||||||
// RootKey is the filepath to the root.key file used by Unbound
|
// Servers information filepath.
|
||||||
RootKey models.Filepath = "/etc/unbound/root.key"
|
ServersData = "/gluetun/servers.json"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,90 +1,663 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"net"
|
||||||
"strings"
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
)
|
||||||
)
|
|
||||||
|
//nolint:lll
|
||||||
const (
|
const (
|
||||||
// PIAEncryptionNormal is the normal level of encryption for communication with PIA servers
|
PIAEncryptionPresetNormal = "normal"
|
||||||
PIAEncryptionNormal models.PIAEncryption = "normal"
|
PIAEncryptionPresetStrong = "strong"
|
||||||
// PIAEncryptionStrong is the strong level of encryption for communication with PIA servers
|
PiaX509CRLNormal = "MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EWB4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Reze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqyMR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A=="
|
||||||
PIAEncryptionStrong models.PIAEncryption = "strong"
|
PiaX509CRLStrong = "MIIDWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAgEAppFfEpGsasjB1QgJcosGpzbf2kfRhM84o2TlqY1ua+Gi5TMdKydA3LJcNTjlI9a0TYAJfeRX5IkpoglSUuHuJgXhP3nEvX10mjXDpcu/YvM8TdE5JV2+EGqZ80kFtBeOq94WcpiVKFTR4fO+VkOK9zwspFfb1cNs9rHvgJ1QMkRUF8PpLN6AkntHY0+6DnigtSaKqldqjKTDTv2OeH3nPoh80SGrt0oCOmYKfWTJGpggMGKvIdvU3vH9+EuILZKKIskt+1dwdfA5Bkz1GLmiQG7+9ZZBQUjBG9Dos4hfX/rwJ3eU8oUIm4WoTz9rb71SOEuUUjP5NPy9HNx2vx+cVvLsTF4ZDZaUztW9o9JmIURDtbeyqxuHN3prlPWB6aj73IIm2dsDQvs3XXwRIxs8NwLbJ6CyEuvEOVCskdM8rdADWx1J0lRNlOJ0Z8ieLLEmYAA834VN1SboB6wJIAPxQU3rcBhXqO9y8aa2oRMg8NxZ5gr+PnKVMqag1x0IxbIgLxtkXQvxXxQHEMSODzvcOfK/nBRBsqTj30P+R87sU8titOoxNeRnBDRNhdEy/QGAqGh62ShPpQUCJdnKRiRTjnil9hMQHevoSuFKeEMO30FQL7BZyo37GFU+q1WPCplVZgCP9hC8Rn5K2+f6KLFo5bhtowSmu+GY1yZtg+RTtsA="
|
||||||
)
|
PIACertificateNormal = "MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXDL1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzXlH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWpcdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RCOfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tLy8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZOsqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpMb3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2VzczEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5jb22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAna5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xUryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK37pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyCGohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUtYDQ8z9v+DMO6iwyIDRiU"
|
||||||
|
PIACertificateStrong = "MIIHqzCCBZOgAwIBAgIJAJ0u+vODZJntMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzQwMzNaFw0zNDA0MTIxNzQwMzNaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVkhjumaqBbL8aSgj6xbX1QPTfTd1qHsAZd2B97m8Vw31c/2yQgZNf5qZY0+jOIHULNDe4R9TIvyBEbvnAg/OkPw8n/+ScgYOeH876VUXzjLDBnDb8DLr/+w9oVsuDeFJ9KV2UFM1OYX0SnkHnrYAN2QLF98ESK4NCSU01h5zkcgmQ+qKSfA9Ny0/UpsKPBFqsQ25NvjDWFhCpeqCHKUJ4Be27CDbSl7lAkBuHMPHJs8f8xPgAbHRXZOxVCpayZ2SNDfCwsnGWpWFoMGvdMbygngCn6jA/W1VSFOlRlfLuuGe7QFfDwA0jaLCxuWt/BgZylp7tAzYKR8lnWmtUCPm4+BtjyVDYtDCiGBD9Z4P13RFWvJHw5aapx/5W/CuvVyI7pKwvc2IT+KPxCUhH1XI8ca5RN3C9NoPJJf6qpg4g0rJH3aaWkoMRrYvQ+5PXXYUzjtRHImghRGd/ydERYoAZXuGSbPkm9Y/p2X8unLcW+F0xpJD98+ZI+tzSsI99Zs5wijSUGYr9/j18KHFTMQ8n+1jauc5bCCegN27dPeKXNSZ5riXFL2XX6BkY68y58UaNzmeGMiUL9BOV1iV+PMb7B7PYs7oFLjAhh0EdyvfHkrh/ZV9BEhtFa7yXp8XR0J6vz1YV9R6DYJmLjOEbhU8N0gc3tZm4Qz39lIIG6w3FDAgMBAAGjggFUMIIBUDAdBgNVHQ4EFgQUrsRtyWJftjpdRM0+925Y6Cl08SUwggEfBgNVHSMEggEWMIIBEoAUrsRtyWJftjpdRM0+925Y6Cl08SWhge6kgeswgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tggkAnS7684Nkme0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOCAgEAJsfhsPk3r8kLXLxY+v+vHzbr4ufNtqnL9/1Uuf8NrsCtpXAoyZ0YqfbkWx3NHTZ7OE9ZRhdMP/RqHQE1p4N4Sa1nZKhTKasV6KhHDqSCt/dvEm89xWm2MVA7nyzQxVlHa9AkcBaemcXEiyT19XdpiXOP4Vhs+J1R5m8zQOxZlV1GtF9vsXmJqWZpOVPmZ8f35BCsYPvv4yMewnrtAC8PFEK/bOPeYcKN50bol22QYaZuLfpkHfNiFTnfMh8sl/ablPyNY7DUNiP5DRcMdIwmfGQxR5WEQoHL3yPJ42LkB5zs6jIm26DGNXfwura/mi105+ENH1CaROtRYwkiHb08U6qLXXJz80mWJkT90nr8Asj35xN2cUppg74nG3YVav/38P48T56hG1NHbYF5uOCske19F6wi9maUoto/3vEr0rnXJUp2KODmKdvBI7co245lHBABWikk8VfejQSlCtDBXn644ZMtAdoxKNfR2WTFVEwJiyd1Fzx0yujuiXDROLhISLQDRjVVAvawrAtLZWYK31bY7KlezPlQnl/D9Asxe85l8jO5+0LdJ6VyOs/Hd4w52alDW/MFySDZSfQHMTIc30hLBJ8OnCEIvluVQQ2UQvoW+no177N9L2Y+M9TcTA62ZyMXShHQGeh20rb4kK8f+iFX8NxtdHVSkxMEFSfDDyQ="
|
||||||
const (
|
)
|
||||||
PIAX509CRL_NORMAL = "MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EWB4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Reze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqyMR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A=="
|
|
||||||
PIAX509CRL_STRONG = "MIIDWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAgEAppFfEpGsasjB1QgJcosGpzbf2kfRhM84o2TlqY1ua+Gi5TMdKydA3LJcNTjlI9a0TYAJfeRX5IkpoglSUuHuJgXhP3nEvX10mjXDpcu/YvM8TdE5JV2+EGqZ80kFtBeOq94WcpiVKFTR4fO+VkOK9zwspFfb1cNs9rHvgJ1QMkRUF8PpLN6AkntHY0+6DnigtSaKqldqjKTDTv2OeH3nPoh80SGrt0oCOmYKfWTJGpggMGKvIdvU3vH9+EuILZKKIskt+1dwdfA5Bkz1GLmiQG7+9ZZBQUjBG9Dos4hfX/rwJ3eU8oUIm4WoTz9rb71SOEuUUjP5NPy9HNx2vx+cVvLsTF4ZDZaUztW9o9JmIURDtbeyqxuHN3prlPWB6aj73IIm2dsDQvs3XXwRIxs8NwLbJ6CyEuvEOVCskdM8rdADWx1J0lRNlOJ0Z8ieLLEmYAA834VN1SboB6wJIAPxQU3rcBhXqO9y8aa2oRMg8NxZ5gr+PnKVMqag1x0IxbIgLxtkXQvxXxQHEMSODzvcOfK/nBRBsqTj30P+R87sU8titOoxNeRnBDRNhdEy/QGAqGh62ShPpQUCJdnKRiRTjnil9hMQHevoSuFKeEMO30FQL7BZyo37GFU+q1WPCplVZgCP9hC8Rn5K2+f6KLFo5bhtowSmu+GY1yZtg+RTtsA="
|
func PIAGeoChoices() (choices []string) {
|
||||||
PIACertificate_NORMAL = "MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXDL1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzXlH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWpcdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RCOfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tLy8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZOsqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpMb3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2VzczEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5jb22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAna5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xUryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK37pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyCGohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUtYDQ8z9v+DMO6iwyIDRiU"
|
servers := PIAServers()
|
||||||
PIACertificate_STRONG = "MIIHqzCCBZOgAwIBAgIJAJ0u+vODZJntMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzQwMzNaFw0zNDA0MTIxNzQwMzNaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVkhjumaqBbL8aSgj6xbX1QPTfTd1qHsAZd2B97m8Vw31c/2yQgZNf5qZY0+jOIHULNDe4R9TIvyBEbvnAg/OkPw8n/+ScgYOeH876VUXzjLDBnDb8DLr/+w9oVsuDeFJ9KV2UFM1OYX0SnkHnrYAN2QLF98ESK4NCSU01h5zkcgmQ+qKSfA9Ny0/UpsKPBFqsQ25NvjDWFhCpeqCHKUJ4Be27CDbSl7lAkBuHMPHJs8f8xPgAbHRXZOxVCpayZ2SNDfCwsnGWpWFoMGvdMbygngCn6jA/W1VSFOlRlfLuuGe7QFfDwA0jaLCxuWt/BgZylp7tAzYKR8lnWmtUCPm4+BtjyVDYtDCiGBD9Z4P13RFWvJHw5aapx/5W/CuvVyI7pKwvc2IT+KPxCUhH1XI8ca5RN3C9NoPJJf6qpg4g0rJH3aaWkoMRrYvQ+5PXXYUzjtRHImghRGd/ydERYoAZXuGSbPkm9Y/p2X8unLcW+F0xpJD98+ZI+tzSsI99Zs5wijSUGYr9/j18KHFTMQ8n+1jauc5bCCegN27dPeKXNSZ5riXFL2XX6BkY68y58UaNzmeGMiUL9BOV1iV+PMb7B7PYs7oFLjAhh0EdyvfHkrh/ZV9BEhtFa7yXp8XR0J6vz1YV9R6DYJmLjOEbhU8N0gc3tZm4Qz39lIIG6w3FDAgMBAAGjggFUMIIBUDAdBgNVHQ4EFgQUrsRtyWJftjpdRM0+925Y6Cl08SUwggEfBgNVHSMEggEWMIIBEoAUrsRtyWJftjpdRM0+925Y6Cl08SWhge6kgeswgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tggkAnS7684Nkme0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOCAgEAJsfhsPk3r8kLXLxY+v+vHzbr4ufNtqnL9/1Uuf8NrsCtpXAoyZ0YqfbkWx3NHTZ7OE9ZRhdMP/RqHQE1p4N4Sa1nZKhTKasV6KhHDqSCt/dvEm89xWm2MVA7nyzQxVlHa9AkcBaemcXEiyT19XdpiXOP4Vhs+J1R5m8zQOxZlV1GtF9vsXmJqWZpOVPmZ8f35BCsYPvv4yMewnrtAC8PFEK/bOPeYcKN50bol22QYaZuLfpkHfNiFTnfMh8sl/ablPyNY7DUNiP5DRcMdIwmfGQxR5WEQoHL3yPJ42LkB5zs6jIm26DGNXfwura/mi105+ENH1CaROtRYwkiHb08U6qLXXJz80mWJkT90nr8Asj35xN2cUppg74nG3YVav/38P48T56hG1NHbYF5uOCske19F6wi9maUoto/3vEr0rnXJUp2KODmKdvBI7co245lHBABWikk8VfejQSlCtDBXn644ZMtAdoxKNfR2WTFVEwJiyd1Fzx0yujuiXDROLhISLQDRjVVAvawrAtLZWYK31bY7KlezPlQnl/D9Asxe85l8jO5+0LdJ6VyOs/Hd4w52alDW/MFySDZSfQHMTIc30hLBJ8OnCEIvluVQQ2UQvoW+no177N9L2Y+M9TcTA62ZyMXShHQGeh20rb4kK8f+iFX8NxtdHVSkxMEFSfDDyQ="
|
choices = make([]string, len(servers))
|
||||||
)
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Region
|
||||||
func PIAGeoChoices() []string {
|
}
|
||||||
return []string{"AU Melbourne", "AU Perth", "AU Sydney", "Austria", "Belgium", "CA Montreal", "CA Toronto", "CA Vancouver", "Czech Republic", "DE Berlin", "DE Frankfurt", "Denmark", "Finland", "France", "Hong Kong", "Hungary", "India", "Ireland", "Israel", "Italy", "Japan", "Luxembourg", "Mexico", "Netherlands", "New Zealand", "Norway", "Poland", "Romania", "Singapore", "Spain", "Sweden", "Switzerland", "UAE", "UK London", "UK Manchester", "UK Southampton", "US Atlanta", "US California", "US Chicago", "US Denver", "US East", "US Florida", "US Houston", "US Las Vegas", "US New York City", "US Seattle", "US Silicon Valley", "US Texas", "US Washington DC", "US West"}
|
return choices
|
||||||
}
|
}
|
||||||
|
|
||||||
func PIAGeoToSubdomainMapping(region models.PIARegion) (subdomain string, err error) {
|
//nolint:lll
|
||||||
mapping := map[models.PIARegion]string{
|
// PIAServers returns a slice of all the server information for PIA.
|
||||||
models.PIARegion("AU Melbourne"): "au-melbourne",
|
func PIAServers() []models.PIAServer {
|
||||||
models.PIARegion("AU Perth"): "au-perth",
|
return []models.PIAServer{
|
||||||
models.PIARegion("AU Sydney"): "au-sydney",
|
{Region: "AU Melbourne", ServerName: "melbourne402", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 220}},
|
||||||
models.PIARegion("Austria"): "austria",
|
{Region: "AU Melbourne", ServerName: "melbourne402", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 240}},
|
||||||
models.PIARegion("Belgium"): "belgium",
|
{Region: "AU Melbourne", ServerName: "melbourne403", Protocol: "udp", PortForward: true, IP: net.IP{103, 2, 198, 75}},
|
||||||
models.PIARegion("CA Montreal"): "ca-montreal",
|
{Region: "AU Melbourne", ServerName: "melbourne403", Protocol: "udp", PortForward: true, IP: net.IP{103, 2, 198, 78}},
|
||||||
models.PIARegion("CA Toronto"): "ca-toronto",
|
{Region: "AU Melbourne", ServerName: "melbourne406", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 153}},
|
||||||
models.PIARegion("CA Vancouver"): "ca-vancouver",
|
{Region: "AU Melbourne", ServerName: "melbourne406", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 149}},
|
||||||
models.PIARegion("Czech Republic"): "czech",
|
{Region: "AU Melbourne", ServerName: "melbourne413", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 126}},
|
||||||
models.PIARegion("DE Berlin"): "de-berlin",
|
{Region: "AU Melbourne", ServerName: "melbourne413", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 116}},
|
||||||
models.PIARegion("DE Frankfurt"): "de-frankfurt",
|
{Region: "AU Melbourne", ServerName: "melbourne414", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 103}},
|
||||||
models.PIARegion("Denmark"): "denmark",
|
{Region: "AU Melbourne", ServerName: "melbourne414", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 74, 110}},
|
||||||
models.PIARegion("Finland"): "fi",
|
{Region: "AU Perth", ServerName: "perth403", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 205, 148}},
|
||||||
models.PIARegion("France"): "france",
|
{Region: "AU Perth", ServerName: "perth403", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 205, 154}},
|
||||||
models.PIARegion("Hong Kong"): "hk",
|
{Region: "AU Perth", ServerName: "perth404", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 205, 186}},
|
||||||
models.PIARegion("Hungary"): "hungary",
|
{Region: "AU Perth", ServerName: "perth404", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 205, 179}},
|
||||||
models.PIARegion("India"): "in",
|
{Region: "AU Perth", ServerName: "perth405", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 205, 139}},
|
||||||
models.PIARegion("Ireland"): "ireland",
|
{Region: "AU Perth", ServerName: "perth405", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 205, 139}},
|
||||||
models.PIARegion("Israel"): "israel",
|
{Region: "AU Sydney", ServerName: "sydney403", Protocol: "udp", PortForward: true, IP: net.IP{117, 120, 9, 42}},
|
||||||
models.PIARegion("Italy"): "italy",
|
{Region: "AU Sydney", ServerName: "sydney403", Protocol: "udp", PortForward: true, IP: net.IP{117, 120, 9, 49}},
|
||||||
models.PIARegion("Japan"): "japan",
|
{Region: "AU Sydney", ServerName: "sydney409", Protocol: "udp", PortForward: true, IP: net.IP{117, 120, 10, 143}},
|
||||||
models.PIARegion("Luxembourg"): "lu",
|
{Region: "AU Sydney", ServerName: "sydney409", Protocol: "udp", PortForward: true, IP: net.IP{117, 120, 10, 144}},
|
||||||
models.PIARegion("Mexico"): "mexico",
|
{Region: "AU Sydney", ServerName: "sydney410", Protocol: "udp", PortForward: true, IP: net.IP{117, 120, 10, 104}},
|
||||||
models.PIARegion("Netherlands"): "nl",
|
{Region: "AU Sydney", ServerName: "sydney410", Protocol: "udp", PortForward: true, IP: net.IP{117, 120, 10, 123}},
|
||||||
models.PIARegion("New Zealand"): "nz",
|
{Region: "AU Sydney", ServerName: "sydney413", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 76, 84}},
|
||||||
models.PIARegion("Norway"): "no",
|
{Region: "AU Sydney", ServerName: "sydney413", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 76, 93}},
|
||||||
models.PIARegion("Poland"): "poland",
|
{Region: "AU Sydney", ServerName: "sydney414", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 76, 99}},
|
||||||
models.PIARegion("Romania"): "ro",
|
{Region: "AU Sydney", ServerName: "sydney414", Protocol: "udp", PortForward: true, IP: net.IP{27, 50, 76, 103}},
|
||||||
models.PIARegion("Singapore"): "sg",
|
{Region: "Albania", ServerName: "tirana401", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 133}},
|
||||||
models.PIARegion("Spain"): "spain",
|
{Region: "Albania", ServerName: "tirana401", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 133}},
|
||||||
models.PIARegion("Sweden"): "sweden",
|
{Region: "Albania", ServerName: "tirana402", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 123}},
|
||||||
models.PIARegion("Switzerland"): "swiss",
|
{Region: "Albania", ServerName: "tirana402", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 118}},
|
||||||
models.PIARegion("UAE"): "ae",
|
{Region: "Albania", ServerName: "tirana403", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 68}},
|
||||||
models.PIARegion("UK London"): "uk-london",
|
{Region: "Albania", ServerName: "tirana403", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 70}},
|
||||||
models.PIARegion("UK Manchester"): "uk-manchester",
|
{Region: "Albania", ServerName: "tirana404", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 55}},
|
||||||
models.PIARegion("UK Southampton"): "uk-southampton",
|
{Region: "Albania", ServerName: "tirana404", Protocol: "udp", PortForward: true, IP: net.IP{31, 171, 154, 61}},
|
||||||
models.PIARegion("US Atlanta"): "us-atlanta",
|
{Region: "Algeria", ServerName: "algiers403", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 228, 4}},
|
||||||
models.PIARegion("US California"): "us-california",
|
{Region: "Algeria", ServerName: "algiers403", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 228, 4}},
|
||||||
models.PIARegion("US Chicago"): "us-chicago",
|
{Region: "Algeria", ServerName: "algiers404", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 228, 24}},
|
||||||
models.PIARegion("US Denver"): "us-denver",
|
{Region: "Algeria", ServerName: "algiers404", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 228, 26}},
|
||||||
models.PIARegion("US East"): "us-east",
|
{Region: "Andorra", ServerName: "andorra403", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 82, 9}},
|
||||||
models.PIARegion("US Florida"): "us-florida",
|
{Region: "Andorra", ServerName: "andorra403", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 82, 5}},
|
||||||
models.PIARegion("US Houston"): "us-houston",
|
{Region: "Andorra", ServerName: "andorra404", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 82, 25}},
|
||||||
models.PIARegion("US Las Vegas"): "us-lasvegas",
|
{Region: "Andorra", ServerName: "andorra404", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 82, 24}},
|
||||||
models.PIARegion("US New York City"): "us-newyorkcity",
|
{Region: "Andorra", ServerName: "andorra405", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 82, 38}},
|
||||||
models.PIARegion("US Seattle"): "us-seattle",
|
{Region: "Andorra", ServerName: "andorra405", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 82, 38}},
|
||||||
models.PIARegion("US Silicon Valley"): "us-siliconvalley",
|
{Region: "Argentina", ServerName: "buenosaires401", Protocol: "udp", PortForward: true, IP: net.IP{190, 106, 134, 83}},
|
||||||
models.PIARegion("US Texas"): "us-texas",
|
{Region: "Argentina", ServerName: "buenosaires401", Protocol: "udp", PortForward: true, IP: net.IP{190, 106, 134, 83}},
|
||||||
models.PIARegion("US Washington DC"): "us-washingtondc",
|
{Region: "Armenia", ServerName: "armenia403", Protocol: "udp", PortForward: true, IP: net.IP{185, 253, 160, 5}},
|
||||||
models.PIARegion("US West"): "us-west",
|
{Region: "Armenia", ServerName: "armenia403", Protocol: "udp", PortForward: true, IP: net.IP{185, 253, 160, 4}},
|
||||||
}
|
{Region: "Austria", ServerName: "vienna402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 60, 45}},
|
||||||
subdomain, ok := mapping[region]
|
{Region: "Austria", ServerName: "vienna402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 60, 27}},
|
||||||
if !ok {
|
{Region: "Austria", ServerName: "vienna403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 60, 68}},
|
||||||
return "", fmt.Errorf("PIA region %q does not exist and can only be one of ", strings.Join(PIAGeoChoices(), ","))
|
{Region: "Austria", ServerName: "vienna403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 60, 70}},
|
||||||
}
|
{Region: "Bahamas", ServerName: "bahamas403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 238, 24}},
|
||||||
return subdomain, nil
|
{Region: "Bahamas", ServerName: "bahamas403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 238, 18}},
|
||||||
}
|
{Region: "Bahamas", ServerName: "bahamas404", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 238, 6}},
|
||||||
|
{Region: "Bahamas", ServerName: "bahamas404", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 238, 13}},
|
||||||
const (
|
{Region: "Bangladesh", ServerName: "bangladesh403", Protocol: "udp", PortForward: true, IP: net.IP{84, 252, 93, 14}},
|
||||||
PIAPortForwardURL models.URL = "http://209.222.18.222:2000"
|
{Region: "Bangladesh", ServerName: "bangladesh403", Protocol: "udp", PortForward: true, IP: net.IP{84, 252, 93, 9}},
|
||||||
)
|
{Region: "Belgium", ServerName: "brussels401", Protocol: "udp", PortForward: true, IP: net.IP{89, 249, 73, 212}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels401", Protocol: "udp", PortForward: true, IP: net.IP{89, 249, 73, 213}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels402", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 211, 253}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels402", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 211, 246}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels406", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 115, 28}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels406", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 115, 18}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels409", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 123, 6}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels409", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 123, 8}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels411", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 123, 57}},
|
||||||
|
{Region: "Belgium", ServerName: "brussels411", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 123, 59}},
|
||||||
|
{Region: "Bosnia and Herzegovina", ServerName: "sarajevo402", Protocol: "udp", PortForward: true, IP: net.IP{185, 212, 111, 63}},
|
||||||
|
{Region: "Bosnia and Herzegovina", ServerName: "sarajevo402", Protocol: "udp", PortForward: true, IP: net.IP{185, 212, 111, 68}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo401", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 180, 228}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo401", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 180, 229}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo402", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 177, 59}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo402", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 177, 58}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo403", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 177, 118}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo403", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 177, 125}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo404", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 180, 244}},
|
||||||
|
{Region: "Brazil", ServerName: "saopaolo404", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 180, 249}},
|
||||||
|
{Region: "Bulgaria", ServerName: "sofia402", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 221, 87}},
|
||||||
|
{Region: "Bulgaria", ServerName: "sofia402", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 221, 83}},
|
||||||
|
{Region: "Bulgaria", ServerName: "sofia403", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 221, 76}},
|
||||||
|
{Region: "Bulgaria", ServerName: "sofia403", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 221, 67}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal404", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 71, 178}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal404", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 71, 173}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal406", Protocol: "udp", PortForward: true, IP: net.IP{199, 36, 223, 15}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal406", Protocol: "udp", PortForward: true, IP: net.IP{199, 36, 223, 36}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal409", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 68, 33}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal409", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 68, 16}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal410", Protocol: "udp", PortForward: true, IP: net.IP{199, 36, 223, 204}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal410", Protocol: "udp", PortForward: true, IP: net.IP{199, 36, 223, 240}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal411", Protocol: "udp", PortForward: true, IP: net.IP{199, 36, 223, 168}},
|
||||||
|
{Region: "CA Montreal", ServerName: "montreal411", Protocol: "udp", PortForward: true, IP: net.IP{199, 36, 223, 155}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario401", Protocol: "udp", PortForward: true, IP: net.IP{172, 83, 47, 128}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario401", Protocol: "udp", PortForward: true, IP: net.IP{172, 83, 47, 97}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario402", Protocol: "udp", PortForward: true, IP: net.IP{172, 83, 47, 153}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario402", Protocol: "udp", PortForward: true, IP: net.IP{172, 83, 47, 153}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario406", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 80, 163}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario406", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 80, 140}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario407", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 80, 10}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario407", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 80, 38}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario409", Protocol: "udp", PortForward: true, IP: net.IP{66, 115, 145, 203}},
|
||||||
|
{Region: "CA Ontario", ServerName: "ontario409", Protocol: "udp", PortForward: true, IP: net.IP{66, 115, 145, 230}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto403", Protocol: "udp", PortForward: true, IP: net.IP{66, 115, 142, 67}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto403", Protocol: "udp", PortForward: true, IP: net.IP{66, 115, 142, 74}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto414", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 40, 4}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto414", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 40, 20}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto417", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 40, 118}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto417", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 40, 96}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto418", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 40, 153}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto418", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 40, 145}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto425", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 42, 119}},
|
||||||
|
{Region: "CA Toronto", ServerName: "toronto425", Protocol: "udp", PortForward: true, IP: net.IP{154, 3, 42, 115}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver401", Protocol: "udp", PortForward: true, IP: net.IP{162, 216, 47, 48}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver401", Protocol: "udp", PortForward: true, IP: net.IP{162, 216, 47, 48}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver406", Protocol: "udp", PortForward: true, IP: net.IP{162, 216, 47, 205}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver406", Protocol: "udp", PortForward: true, IP: net.IP{162, 216, 47, 203}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver407", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 89, 67}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver407", Protocol: "udp", PortForward: true, IP: net.IP{172, 98, 89, 44}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver411", Protocol: "udp", PortForward: true, IP: net.IP{208, 78, 42, 138}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver411", Protocol: "udp", PortForward: true, IP: net.IP{208, 78, 42, 133}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver412", Protocol: "udp", PortForward: true, IP: net.IP{208, 78, 42, 226}},
|
||||||
|
{Region: "CA Vancouver", ServerName: "vancouver412", Protocol: "udp", PortForward: true, IP: net.IP{208, 78, 42, 247}},
|
||||||
|
{Region: "Cambodia", ServerName: "cambodia401", Protocol: "udp", PortForward: true, IP: net.IP{188, 215, 235, 110}},
|
||||||
|
{Region: "Cambodia", ServerName: "cambodia401", Protocol: "udp", PortForward: true, IP: net.IP{188, 215, 235, 100}},
|
||||||
|
{Region: "Cambodia", ServerName: "cambodia402", Protocol: "udp", PortForward: true, IP: net.IP{188, 215, 235, 125}},
|
||||||
|
{Region: "Cambodia", ServerName: "cambodia402", Protocol: "udp", PortForward: true, IP: net.IP{188, 215, 235, 119}},
|
||||||
|
{Region: "China", ServerName: "china404", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 80, 9}},
|
||||||
|
{Region: "China", ServerName: "china404", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 80, 8}},
|
||||||
|
{Region: "Cyprus", ServerName: "cyprus403", Protocol: "udp", PortForward: true, IP: net.IP{185, 253, 162, 3}},
|
||||||
|
{Region: "Cyprus", ServerName: "cyprus403", Protocol: "udp", PortForward: true, IP: net.IP{185, 253, 162, 8}},
|
||||||
|
{Region: "Czech Republic", ServerName: "prague401", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 39, 74}},
|
||||||
|
{Region: "Czech Republic", ServerName: "prague401", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 39, 73}},
|
||||||
|
{Region: "Czech Republic", ServerName: "prague402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 39, 154}},
|
||||||
|
{Region: "Czech Republic", ServerName: "prague402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 39, 139}},
|
||||||
|
{Region: "Czech Republic", ServerName: "prague403", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 39, 195}},
|
||||||
|
{Region: "Czech Republic", ServerName: "prague403", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 39, 195}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin416", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 5}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin416", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 6}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin417", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 30}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin417", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 25}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin421", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 88}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin421", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 88}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin424", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 136}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin424", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 126}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin425", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 151}},
|
||||||
|
{Region: "DE Berlin", ServerName: "berlin425", Protocol: "udp", PortForward: true, IP: net.IP{154, 13, 1, 145}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt402", Protocol: "udp", PortForward: true, IP: net.IP{195, 181, 170, 229}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 57, 217}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt405", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 57, 45}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt405", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 57, 3}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt407", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 18, 174}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt407", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 18, 136}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt408", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 18, 98}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt408", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 18, 104}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt410", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 57, 184}},
|
||||||
|
{Region: "DE Frankfurt", ServerName: "frankfurt410", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 57, 184}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen402", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 75}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen402", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 89}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen403", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 103}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen403", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 103}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen404", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 176}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen404", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 174}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen405", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 35}},
|
||||||
|
{Region: "Denmark", ServerName: "copenhagen405", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 94, 47}},
|
||||||
|
{Region: "Egypt", ServerName: "cairo401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 122, 107}},
|
||||||
|
{Region: "Egypt", ServerName: "cairo401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 122, 100}},
|
||||||
|
{Region: "Egypt", ServerName: "cairo402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 122, 118}},
|
||||||
|
{Region: "Egypt", ServerName: "cairo402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 122, 118}},
|
||||||
|
{Region: "Estonia", ServerName: "talinn401", Protocol: "udp", PortForward: true, IP: net.IP{77, 247, 111, 138}},
|
||||||
|
{Region: "Estonia", ServerName: "talinn401", Protocol: "udp", PortForward: true, IP: net.IP{77, 247, 111, 138}},
|
||||||
|
{Region: "Estonia", ServerName: "talinn402", Protocol: "udp", PortForward: true, IP: net.IP{95, 153, 31, 68}},
|
||||||
|
{Region: "Estonia", ServerName: "talinn402", Protocol: "udp", PortForward: true, IP: net.IP{95, 153, 31, 75}},
|
||||||
|
{Region: "Finland", ServerName: "helsinki401", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 89, 23}},
|
||||||
|
{Region: "Finland", ServerName: "helsinki401", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 89, 27}},
|
||||||
|
{Region: "Finland", ServerName: "helsinki402", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 89, 57}},
|
||||||
|
{Region: "Finland", ServerName: "helsinki402", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 89, 57}},
|
||||||
|
{Region: "Finland", ServerName: "helsinki404", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 89, 93}},
|
||||||
|
{Region: "Finland", ServerName: "helsinki404", Protocol: "udp", PortForward: true, IP: net.IP{188, 126, 89, 84}},
|
||||||
|
{Region: "France", ServerName: "paris402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 63, 170}},
|
||||||
|
{Region: "France", ServerName: "paris402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 63, 178}},
|
||||||
|
{Region: "France", ServerName: "paris404", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 63, 4}},
|
||||||
|
{Region: "France", ServerName: "paris404", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 63, 4}},
|
||||||
|
{Region: "France", ServerName: "paris405", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 63, 103}},
|
||||||
|
{Region: "France", ServerName: "paris405", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 63, 93}},
|
||||||
|
{Region: "France", ServerName: "paris406", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 57, 148}},
|
||||||
|
{Region: "France", ServerName: "paris406", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 57, 165}},
|
||||||
|
{Region: "France", ServerName: "paris407", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 57, 239}},
|
||||||
|
{Region: "France", ServerName: "paris407", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 57, 203}},
|
||||||
|
{Region: "Georgia", ServerName: "georgia403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 236, 6}},
|
||||||
|
{Region: "Georgia", ServerName: "georgia403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 236, 4}},
|
||||||
|
{Region: "Greece", ServerName: "athens401", Protocol: "udp", PortForward: true, IP: net.IP{154, 57, 3, 87}},
|
||||||
|
{Region: "Greece", ServerName: "athens401", Protocol: "udp", PortForward: true, IP: net.IP{154, 57, 3, 77}},
|
||||||
|
{Region: "Greece", ServerName: "athens402", Protocol: "udp", PortForward: true, IP: net.IP{154, 57, 3, 93}},
|
||||||
|
{Region: "Greece", ServerName: "athens402", Protocol: "udp", PortForward: true, IP: net.IP{154, 57, 3, 96}},
|
||||||
|
{Region: "Greece", ServerName: "athens403", Protocol: "udp", PortForward: true, IP: net.IP{154, 57, 3, 117}},
|
||||||
|
{Region: "Greece", ServerName: "athens403", Protocol: "udp", PortForward: true, IP: net.IP{154, 57, 3, 114}},
|
||||||
|
{Region: "Greenland", ServerName: "greenland403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 120, 134}},
|
||||||
|
{Region: "Greenland", ServerName: "greenland403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 120, 131}},
|
||||||
|
{Region: "Greenland", ServerName: "greenland404", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 120, 148}},
|
||||||
|
{Region: "Greenland", ServerName: "greenland404", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 120, 156}},
|
||||||
|
{Region: "Hong Kong", ServerName: "china403", Protocol: "udp", PortForward: true, IP: net.IP{86, 107, 104, 213}},
|
||||||
|
{Region: "Hong Kong", ServerName: "china403", Protocol: "udp", PortForward: true, IP: net.IP{86, 107, 104, 214}},
|
||||||
|
{Region: "Hong Kong", ServerName: "hongkong402", Protocol: "udp", PortForward: true, IP: net.IP{86, 107, 104, 244}},
|
||||||
|
{Region: "Hong Kong", ServerName: "hongkong402", Protocol: "udp", PortForward: true, IP: net.IP{86, 107, 104, 243}},
|
||||||
|
{Region: "Hong Kong", ServerName: "hongkong403", Protocol: "udp", PortForward: true, IP: net.IP{91, 219, 213, 7}},
|
||||||
|
{Region: "Hong Kong", ServerName: "hongkong403", Protocol: "udp", PortForward: true, IP: net.IP{91, 219, 213, 18}},
|
||||||
|
{Region: "Hungary", ServerName: "budapest401", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 192, 218}},
|
||||||
|
{Region: "Hungary", ServerName: "budapest401", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 192, 222}},
|
||||||
|
{Region: "Hungary", ServerName: "budapest402", Protocol: "udp", PortForward: true, IP: net.IP{86, 106, 74, 116}},
|
||||||
|
{Region: "Hungary", ServerName: "budapest402", Protocol: "udp", PortForward: true, IP: net.IP{86, 106, 74, 116}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik401", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 39}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik401", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 37}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik402", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 84}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik402", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 84}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik403", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 76}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik403", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 67}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik404", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 56}},
|
||||||
|
{Region: "Iceland", ServerName: "reykjavik404", Protocol: "udp", PortForward: true, IP: net.IP{45, 133, 193, 56}},
|
||||||
|
{Region: "India", ServerName: "mumbai401", Protocol: "udp", PortForward: true, IP: net.IP{45, 120, 139, 37}},
|
||||||
|
{Region: "India", ServerName: "mumbai401", Protocol: "udp", PortForward: true, IP: net.IP{45, 120, 139, 33}},
|
||||||
|
{Region: "India", ServerName: "mumbai402", Protocol: "udp", PortForward: true, IP: net.IP{45, 120, 139, 128}},
|
||||||
|
{Region: "India", ServerName: "mumbai402", Protocol: "udp", PortForward: true, IP: net.IP{45, 120, 139, 130}},
|
||||||
|
{Region: "India", ServerName: "mumbai403", Protocol: "udp", PortForward: true, IP: net.IP{103, 150, 187, 4}},
|
||||||
|
{Region: "India", ServerName: "mumbai403", Protocol: "udp", PortForward: true, IP: net.IP{103, 150, 187, 5}},
|
||||||
|
{Region: "India", ServerName: "mumbai405", Protocol: "udp", PortForward: true, IP: net.IP{45, 120, 139, 88}},
|
||||||
|
{Region: "India", ServerName: "mumbai405", Protocol: "udp", PortForward: true, IP: net.IP{45, 120, 139, 98}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin404", Protocol: "udp", PortForward: true, IP: net.IP{193, 56, 252, 20}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin404", Protocol: "udp", PortForward: true, IP: net.IP{193, 56, 252, 20}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin405", Protocol: "udp", PortForward: true, IP: net.IP{193, 56, 252, 10}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin405", Protocol: "udp", PortForward: true, IP: net.IP{193, 56, 252, 8}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin407", Protocol: "udp", PortForward: true, IP: net.IP{193, 56, 252, 236}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin407", Protocol: "udp", PortForward: true, IP: net.IP{193, 56, 252, 230}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin410", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 178, 5}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin410", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 178, 14}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin411", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 178, 26}},
|
||||||
|
{Region: "Ireland", ServerName: "dublin411", Protocol: "udp", PortForward: true, IP: net.IP{188, 241, 178, 26}},
|
||||||
|
{Region: "Isle of Man", ServerName: "douglas403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 124, 13}},
|
||||||
|
{Region: "Isle of Man", ServerName: "douglas403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 124, 9}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem402", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 33}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem402", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 25}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem404", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 50}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem404", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 63}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem405", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 66}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem405", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 76}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem406", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 86}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem406", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 84}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem407", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 98}},
|
||||||
|
{Region: "Israel", ServerName: "jerusalem407", Protocol: "udp", PortForward: true, IP: net.IP{185, 77, 248, 93}},
|
||||||
|
{Region: "Italy", ServerName: "milano402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 41, 14}},
|
||||||
|
{Region: "Italy", ServerName: "milano402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 41, 60}},
|
||||||
|
{Region: "Italy", ServerName: "milano403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 41, 96}},
|
||||||
|
{Region: "Italy", ServerName: "milano403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 41, 66}},
|
||||||
|
{Region: "Japan", ServerName: "tokyo401", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 34, 155}},
|
||||||
|
{Region: "Japan", ServerName: "tokyo401", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 34, 155}},
|
||||||
|
{Region: "Japan", ServerName: "tokyo402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 34, 117}},
|
||||||
|
{Region: "Japan", ServerName: "tokyo402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 34, 113}},
|
||||||
|
{Region: "Japan", ServerName: "tokyo403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 34, 15}},
|
||||||
|
{Region: "Japan", ServerName: "tokyo403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 34, 46}},
|
||||||
|
{Region: "Kazakhstan", ServerName: "kazakhstan403", Protocol: "udp", PortForward: true, IP: net.IP{62, 133, 47, 5}},
|
||||||
|
{Region: "Kazakhstan", ServerName: "kazakhstan403", Protocol: "udp", PortForward: true, IP: net.IP{62, 133, 47, 9}},
|
||||||
|
{Region: "Latvia", ServerName: "riga401", Protocol: "udp", PortForward: true, IP: net.IP{109, 248, 149, 10}},
|
||||||
|
{Region: "Latvia", ServerName: "riga401", Protocol: "udp", PortForward: true, IP: net.IP{109, 248, 149, 4}},
|
||||||
|
{Region: "Latvia", ServerName: "riga402", Protocol: "udp", PortForward: true, IP: net.IP{46, 183, 218, 133}},
|
||||||
|
{Region: "Latvia", ServerName: "riga402", Protocol: "udp", PortForward: true, IP: net.IP{46, 183, 218, 135}},
|
||||||
|
{Region: "Latvia", ServerName: "riga403", Protocol: "udp", PortForward: true, IP: net.IP{46, 183, 218, 153}},
|
||||||
|
{Region: "Latvia", ServerName: "riga403", Protocol: "udp", PortForward: true, IP: net.IP{46, 183, 218, 154}},
|
||||||
|
{Region: "Liechtenstein", ServerName: "liechtenstein403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 122, 8}},
|
||||||
|
{Region: "Liechtenstein", ServerName: "liechtenstein403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 122, 4}},
|
||||||
|
{Region: "Lithuania", ServerName: "vilnius401", Protocol: "udp", PortForward: true, IP: net.IP{85, 206, 165, 173}},
|
||||||
|
{Region: "Lithuania", ServerName: "vilnius401", Protocol: "udp", PortForward: true, IP: net.IP{85, 206, 165, 173}},
|
||||||
|
{Region: "Lithuania", ServerName: "vilnius402", Protocol: "udp", PortForward: true, IP: net.IP{85, 206, 165, 103}},
|
||||||
|
{Region: "Lithuania", ServerName: "vilnius402", Protocol: "udp", PortForward: true, IP: net.IP{85, 206, 165, 106}},
|
||||||
|
{Region: "Lithuania", ServerName: "vilnius403", Protocol: "udp", PortForward: true, IP: net.IP{85, 206, 165, 123}},
|
||||||
|
{Region: "Lithuania", ServerName: "vilnius403", Protocol: "udp", PortForward: true, IP: net.IP{85, 206, 165, 123}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg404", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 110}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg404", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 109}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg405", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 118}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg405", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 119}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg406", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 133}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg406", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 136}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg407", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 156}},
|
||||||
|
{Region: "Luxembourg", ServerName: "luxembourg407", Protocol: "udp", PortForward: true, IP: net.IP{5, 253, 204, 153}},
|
||||||
|
{Region: "Macao", ServerName: "macau403", Protocol: "udp", PortForward: true, IP: net.IP{84, 252, 92, 4}},
|
||||||
|
{Region: "Macao", ServerName: "macau403", Protocol: "udp", PortForward: true, IP: net.IP{84, 252, 92, 4}},
|
||||||
|
{Region: "Macedonia", ServerName: "macedonia401", Protocol: "udp", PortForward: true, IP: net.IP{185, 225, 28, 120}},
|
||||||
|
{Region: "Macedonia", ServerName: "macedonia401", Protocol: "udp", PortForward: true, IP: net.IP{185, 225, 28, 120}},
|
||||||
|
{Region: "Macedonia", ServerName: "macedonia402", Protocol: "udp", PortForward: true, IP: net.IP{185, 225, 28, 140}},
|
||||||
|
{Region: "Macedonia", ServerName: "macedonia402", Protocol: "udp", PortForward: true, IP: net.IP{185, 225, 28, 141}},
|
||||||
|
{Region: "Malta", ServerName: "malta403", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 230, 5}},
|
||||||
|
{Region: "Malta", ServerName: "malta403", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 230, 7}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico403", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 15}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico403", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 10}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico404", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 24}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico404", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 26}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico407", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 71}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico407", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 64}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico409", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 97}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico409", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 96}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico412", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 205}},
|
||||||
|
{Region: "Mexico", ServerName: "mexico412", Protocol: "udp", PortForward: true, IP: net.IP{77, 81, 142, 199}},
|
||||||
|
{Region: "Moldova", ServerName: "chisinau401", Protocol: "udp", PortForward: true, IP: net.IP{178, 175, 129, 39}},
|
||||||
|
{Region: "Moldova", ServerName: "chisinau401", Protocol: "udp", PortForward: true, IP: net.IP{178, 175, 129, 44}},
|
||||||
|
{Region: "Monaco", ServerName: "monaco403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 233, 4}},
|
||||||
|
{Region: "Monaco", ServerName: "monaco403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 233, 3}},
|
||||||
|
{Region: "Mongolia", ServerName: "mongolia403", Protocol: "udp", PortForward: true, IP: net.IP{185, 253, 163, 14}},
|
||||||
|
{Region: "Mongolia", ServerName: "mongolia403", Protocol: "udp", PortForward: true, IP: net.IP{185, 253, 163, 3}},
|
||||||
|
{Region: "Montenegro", ServerName: "montenegro403", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 229, 15}},
|
||||||
|
{Region: "Montenegro", ServerName: "montenegro403", Protocol: "udp", PortForward: true, IP: net.IP{176, 125, 229, 9}},
|
||||||
|
{Region: "Morocco", ServerName: "morocco403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 232, 4}},
|
||||||
|
{Region: "Morocco", ServerName: "morocco403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 232, 12}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam401", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 35, 25}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam401", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 35, 27}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 34, 147}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 34, 156}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam403", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 34, 170}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam403", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 34, 220}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam408", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 43, 187}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam408", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 43, 187}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam420", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 41, 17}},
|
||||||
|
{Region: "Netherlands", ServerName: "amsterdam420", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 41, 25}},
|
||||||
|
{Region: "New Zealand", ServerName: "newzealand403", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 207, 88}},
|
||||||
|
{Region: "New Zealand", ServerName: "newzealand403", Protocol: "udp", PortForward: true, IP: net.IP{43, 250, 207, 84}},
|
||||||
|
{Region: "New Zealand", ServerName: "newzealand404", Protocol: "udp", PortForward: true, IP: net.IP{202, 60, 86, 27}},
|
||||||
|
{Region: "New Zealand", ServerName: "newzealand404", Protocol: "udp", PortForward: true, IP: net.IP{202, 60, 86, 15}},
|
||||||
|
{Region: "New Zealand", ServerName: "newzealand405", Protocol: "udp", PortForward: true, IP: net.IP{202, 60, 86, 99}},
|
||||||
|
{Region: "New Zealand", ServerName: "newzealand405", Protocol: "udp", PortForward: true, IP: net.IP{202, 60, 86, 118}},
|
||||||
|
{Region: "Nigeria", ServerName: "nigeria403", Protocol: "udp", PortForward: true, IP: net.IP{102, 165, 25, 84}},
|
||||||
|
{Region: "Nigeria", ServerName: "nigeria403", Protocol: "udp", PortForward: true, IP: net.IP{102, 165, 25, 90}},
|
||||||
|
{Region: "Nigeria", ServerName: "nigeria404", Protocol: "udp", PortForward: true, IP: net.IP{102, 165, 25, 126}},
|
||||||
|
{Region: "Nigeria", ServerName: "nigeria404", Protocol: "udp", PortForward: true, IP: net.IP{102, 165, 25, 117}},
|
||||||
|
{Region: "Norway", ServerName: "oslo401", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 35}},
|
||||||
|
{Region: "Norway", ServerName: "oslo401", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 39}},
|
||||||
|
{Region: "Norway", ServerName: "oslo402", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 85}},
|
||||||
|
{Region: "Norway", ServerName: "oslo402", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 69}},
|
||||||
|
{Region: "Norway", ServerName: "oslo403", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 107}},
|
||||||
|
{Region: "Norway", ServerName: "oslo403", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 125}},
|
||||||
|
{Region: "Norway", ServerName: "oslo404", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 167}},
|
||||||
|
{Region: "Norway", ServerName: "oslo404", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 122, 176}},
|
||||||
|
{Region: "Panama", ServerName: "panama403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 126, 14}},
|
||||||
|
{Region: "Panama", ServerName: "panama403", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 126, 4}},
|
||||||
|
{Region: "Panama", ServerName: "panama404", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 126, 29}},
|
||||||
|
{Region: "Panama", ServerName: "panama404", Protocol: "udp", PortForward: true, IP: net.IP{91, 90, 126, 23}},
|
||||||
|
{Region: "Philippines", ServerName: "philippines401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 125, 135}},
|
||||||
|
{Region: "Philippines", ServerName: "philippines401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 125, 134}},
|
||||||
|
{Region: "Philippines", ServerName: "philippines402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 125, 147}},
|
||||||
|
{Region: "Philippines", ServerName: "philippines402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 125, 149}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw401", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 209, 244}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw401", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 209, 242}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw402", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 13}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw402", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 4}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw405", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 55}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw405", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 53}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw406", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 68}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw406", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 69}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw409", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 119}},
|
||||||
|
{Region: "Poland", ServerName: "warsaw409", Protocol: "udp", PortForward: true, IP: net.IP{194, 110, 114, 115}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon401", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 75}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon401", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 82}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon402", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 99}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon402", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 96}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon403", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 133}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon403", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 145}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon404", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 115}},
|
||||||
|
{Region: "Portugal", ServerName: "lisbon404", Protocol: "udp", PortForward: true, IP: net.IP{89, 26, 241, 103}},
|
||||||
|
{Region: "Qatar", ServerName: "qatar403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 234, 8}},
|
||||||
|
{Region: "Qatar", ServerName: "qatar403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 234, 6}},
|
||||||
|
{Region: "Romania", ServerName: "romania406", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 52, 19}},
|
||||||
|
{Region: "Romania", ServerName: "romania406", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 52, 33}},
|
||||||
|
{Region: "Romania", ServerName: "romania407", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 54, 153}},
|
||||||
|
{Region: "Romania", ServerName: "romania407", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 54, 154}},
|
||||||
|
{Region: "Romania", ServerName: "romania408", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 54, 70}},
|
||||||
|
{Region: "Romania", ServerName: "romania408", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 54, 116}},
|
||||||
|
{Region: "Romania", ServerName: "romania409", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 54, 43}},
|
||||||
|
{Region: "Romania", ServerName: "romania409", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 54, 43}},
|
||||||
|
{Region: "Saudi Arabia", ServerName: "saudiarabia403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 235, 16}},
|
||||||
|
{Region: "Saudi Arabia", ServerName: "saudiarabia403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 235, 16}},
|
||||||
|
{Region: "Serbia", ServerName: "belgrade401", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 193, 254}},
|
||||||
|
{Region: "Serbia", ServerName: "belgrade401", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 193, 243}},
|
||||||
|
{Region: "Serbia", ServerName: "belgrade402", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 193, 237}},
|
||||||
|
{Region: "Serbia", ServerName: "belgrade402", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 193, 229}},
|
||||||
|
{Region: "Singapore", ServerName: "singapore401", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 57, 175}},
|
||||||
|
{Region: "Singapore", ServerName: "singapore401", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 57, 178}},
|
||||||
|
{Region: "Singapore", ServerName: "singapore402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 57, 108}},
|
||||||
|
{Region: "Singapore", ServerName: "singapore402", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 57, 160}},
|
||||||
|
{Region: "Singapore", ServerName: "singapore403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 57, 89}},
|
||||||
|
{Region: "Singapore", ServerName: "singapore403", Protocol: "udp", PortForward: true, IP: net.IP{156, 146, 57, 89}},
|
||||||
|
{Region: "Slovakia", ServerName: "bratislava401", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 221, 84}},
|
||||||
|
{Region: "Slovakia", ServerName: "bratislava401", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 221, 86}},
|
||||||
|
{Region: "Slovakia", ServerName: "bratislava402", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 221, 214}},
|
||||||
|
{Region: "Slovakia", ServerName: "bratislava402", Protocol: "udp", PortForward: true, IP: net.IP{37, 120, 221, 217}},
|
||||||
|
{Region: "South Africa", ServerName: "johannesburg401", Protocol: "udp", PortForward: true, IP: net.IP{154, 16, 93, 34}},
|
||||||
|
{Region: "South Africa", ServerName: "johannesburg401", Protocol: "udp", PortForward: true, IP: net.IP{154, 16, 93, 35}},
|
||||||
|
{Region: "South Africa", ServerName: "johannesburg403", Protocol: "udp", PortForward: true, IP: net.IP{154, 16, 93, 234}},
|
||||||
|
{Region: "South Africa", ServerName: "johannesburg403", Protocol: "udp", PortForward: true, IP: net.IP{154, 16, 93, 233}},
|
||||||
|
{Region: "Spain", ServerName: "madrid401", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 49, 106}},
|
||||||
|
{Region: "Spain", ServerName: "madrid401", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 49, 116}},
|
||||||
|
{Region: "Spain", ServerName: "madrid402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 49, 34}},
|
||||||
|
{Region: "Spain", ServerName: "madrid402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 49, 25}},
|
||||||
|
{Region: "Sri Lanka", ServerName: "srilanka403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 239, 9}},
|
||||||
|
{Region: "Sri Lanka", ServerName: "srilanka403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 239, 10}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm401", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 33}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm401", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 14}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm402", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 59}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm402", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 60}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm403", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 103}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm403", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 84}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm404", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 129}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm404", Protocol: "udp", PortForward: true, IP: net.IP{195, 246, 120, 118}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm405", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 3, 204}},
|
||||||
|
{Region: "Sweden", ServerName: "stockholm405", Protocol: "udp", PortForward: true, IP: net.IP{46, 246, 3, 190}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich403", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 37, 116}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich403", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 37, 156}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich404", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 37, 105}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich404", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 37, 100}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich405", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 36, 16}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich405", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 36, 16}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich407", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 36, 163}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich407", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 36, 163}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich408", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 36, 184}},
|
||||||
|
{Region: "Switzerland", ServerName: "zurich408", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 36, 175}},
|
||||||
|
{Region: "Taiwan", ServerName: "taiwan401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 106, 69}},
|
||||||
|
{Region: "Taiwan", ServerName: "taiwan401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 106, 68}},
|
||||||
|
{Region: "Taiwan", ServerName: "taiwan402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 106, 89}},
|
||||||
|
{Region: "Taiwan", ServerName: "taiwan402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 106, 89}},
|
||||||
|
{Region: "Taiwan", ServerName: "taiwan403", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 106, 144}},
|
||||||
|
{Region: "Taiwan", ServerName: "taiwan403", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 106, 140}},
|
||||||
|
{Region: "Turkey", ServerName: "istanbul401", Protocol: "udp", PortForward: true, IP: net.IP{188, 213, 34, 70}},
|
||||||
|
{Region: "Turkey", ServerName: "istanbul401", Protocol: "udp", PortForward: true, IP: net.IP{188, 213, 34, 73}},
|
||||||
|
{Region: "Turkey", ServerName: "istanbul402", Protocol: "udp", PortForward: true, IP: net.IP{188, 213, 34, 85}},
|
||||||
|
{Region: "Turkey", ServerName: "istanbul402", Protocol: "udp", PortForward: true, IP: net.IP{188, 213, 34, 86}},
|
||||||
|
{Region: "UK London", ServerName: "london402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 63, 170}},
|
||||||
|
{Region: "UK London", ServerName: "london402", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 63, 140}},
|
||||||
|
{Region: "UK London", ServerName: "london404", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 52, 86}},
|
||||||
|
{Region: "UK London", ServerName: "london404", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 52, 94}},
|
||||||
|
{Region: "UK London", ServerName: "london405", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 53, 53}},
|
||||||
|
{Region: "UK London", ServerName: "london405", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 53, 26}},
|
||||||
|
{Region: "UK London", ServerName: "london412", Protocol: "udp", PortForward: true, IP: net.IP{37, 235, 96, 77}},
|
||||||
|
{Region: "UK London", ServerName: "london412", Protocol: "udp", PortForward: true, IP: net.IP{37, 235, 96, 90}},
|
||||||
|
{Region: "UK London", ServerName: "london414", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 53, 230}},
|
||||||
|
{Region: "UK London", ServerName: "london414", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 53, 194}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london419", Protocol: "udp", PortForward: true, IP: net.IP{37, 235, 97, 19}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london419", Protocol: "udp", PortForward: true, IP: net.IP{37, 235, 97, 16}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london420", Protocol: "udp", PortForward: true, IP: net.IP{37, 235, 96, 203}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london420", Protocol: "udp", PortForward: true, IP: net.IP{37, 235, 96, 199}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london429", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 29, 139}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london429", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 29, 133}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london430", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 29, 146}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london430", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 29, 146}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london431", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 29, 160}},
|
||||||
|
{Region: "UK London - Streaming Optimized", ServerName: "london431", Protocol: "udp", PortForward: true, IP: net.IP{138, 199, 29, 164}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester403", Protocol: "udp", PortForward: true, IP: net.IP{193, 239, 84, 66}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester403", Protocol: "udp", PortForward: true, IP: net.IP{193, 239, 84, 76}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester406", Protocol: "udp", PortForward: true, IP: net.IP{89, 44, 201, 245}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester406", Protocol: "udp", PortForward: true, IP: net.IP{89, 44, 201, 245}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester408", Protocol: "udp", PortForward: true, IP: net.IP{89, 44, 201, 217}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester408", Protocol: "udp", PortForward: true, IP: net.IP{89, 44, 201, 210}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester409", Protocol: "udp", PortForward: true, IP: net.IP{194, 37, 96, 18}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester409", Protocol: "udp", PortForward: true, IP: net.IP{194, 37, 96, 29}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester414", Protocol: "udp", PortForward: true, IP: net.IP{194, 37, 96, 198}},
|
||||||
|
{Region: "UK Manchester", ServerName: "manchester414", Protocol: "udp", PortForward: true, IP: net.IP{194, 37, 96, 206}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton401", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 37, 208}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton401", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 37, 228}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton402", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 37, 144}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton402", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 37, 175}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton405", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 36, 104}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton405", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 36, 113}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton406", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 38, 109}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton406", Protocol: "udp", PortForward: true, IP: net.IP{143, 244, 38, 109}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton410", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 53, 85}},
|
||||||
|
{Region: "UK Southampton", ServerName: "southampton410", Protocol: "udp", PortForward: true, IP: net.IP{212, 102, 53, 84}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta412", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 22, 59}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta412", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 22, 39}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta418", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 22, 229}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta418", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 22, 233}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta419", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 21, 25}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta419", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 21, 33}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta421", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 21, 74}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta421", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 21, 88}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta422", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 21, 103}},
|
||||||
|
{Region: "US Atlanta", ServerName: "atlanta422", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 21, 129}},
|
||||||
|
{Region: "US California", ServerName: "losangeles401", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 48, 24}},
|
||||||
|
{Region: "US California", ServerName: "losangeles401", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 48, 36}},
|
||||||
|
{Region: "US California", ServerName: "losangeles402", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 49, 33}},
|
||||||
|
{Region: "US California", ServerName: "losangeles402", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 49, 43}},
|
||||||
|
{Region: "US California", ServerName: "losangeles404", Protocol: "udp", PortForward: false, IP: net.IP{84, 17, 45, 40}},
|
||||||
|
{Region: "US California", ServerName: "losangeles404", Protocol: "udp", PortForward: false, IP: net.IP{84, 17, 45, 3}},
|
||||||
|
{Region: "US California", ServerName: "losangeles409", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 49, 166}},
|
||||||
|
{Region: "US California", ServerName: "losangeles409", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 49, 166}},
|
||||||
|
{Region: "US California", ServerName: "losangeles418", Protocol: "udp", PortForward: false, IP: net.IP{138, 199, 8, 93}},
|
||||||
|
{Region: "US California", ServerName: "losangeles418", Protocol: "udp", PortForward: false, IP: net.IP{138, 199, 8, 94}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago407", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 28, 73}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago407", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 28, 88}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago410", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 28, 220}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago410", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 28, 249}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago411", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 23, 9}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago411", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 23, 6}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago412", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 23, 64}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago412", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 23, 60}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago418", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 114, 126}},
|
||||||
|
{Region: "US Chicago", ServerName: "chicago418", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 114, 108}},
|
||||||
|
{Region: "US Denver", ServerName: "denver401", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 81, 148}},
|
||||||
|
{Region: "US Denver", ServerName: "denver401", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 81, 154}},
|
||||||
|
{Region: "US Denver", ServerName: "denver402", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 126, 175}},
|
||||||
|
{Region: "US Denver", ServerName: "denver402", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 126, 174}},
|
||||||
|
{Region: "US Denver", ServerName: "denver405", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 110, 125}},
|
||||||
|
{Region: "US Denver", ServerName: "denver405", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 110, 125}},
|
||||||
|
{Region: "US Denver", ServerName: "denver406", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 77, 166}},
|
||||||
|
{Region: "US Denver", ServerName: "denver406", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 77, 183}},
|
||||||
|
{Region: "US Denver", ServerName: "denver408", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 92, 24}},
|
||||||
|
{Region: "US Denver", ServerName: "denver408", Protocol: "udp", PortForward: false, IP: net.IP{70, 39, 92, 28}},
|
||||||
|
{Region: "US East", ServerName: "newjersey401", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 44, 73}},
|
||||||
|
{Region: "US East", ServerName: "newjersey401", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 44, 76}},
|
||||||
|
{Region: "US East", ServerName: "newjersey402", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 45, 85}},
|
||||||
|
{Region: "US East", ServerName: "newjersey402", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 45, 105}},
|
||||||
|
{Region: "US East", ServerName: "newjersey403", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 44, 28}},
|
||||||
|
{Region: "US East", ServerName: "newjersey403", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 44, 43}},
|
||||||
|
{Region: "US East", ServerName: "newjersey407", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 47, 156}},
|
||||||
|
{Region: "US East", ServerName: "newjersey407", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 47, 156}},
|
||||||
|
{Region: "US East", ServerName: "newjersey413", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 45, 190}},
|
||||||
|
{Region: "US East", ServerName: "newjersey413", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 45, 196}},
|
||||||
|
{Region: "US Florida", ServerName: "miami404", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 34, 184}},
|
||||||
|
{Region: "US Florida", ServerName: "miami404", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 34, 184}},
|
||||||
|
{Region: "US Florida", ServerName: "miami405", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 34, 208}},
|
||||||
|
{Region: "US Florida", ServerName: "miami405", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 34, 210}},
|
||||||
|
{Region: "US Florida", ServerName: "miami406", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 42, 13}},
|
||||||
|
{Region: "US Florida", ServerName: "miami406", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 42, 30}},
|
||||||
|
{Region: "US Florida", ServerName: "miami408", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 42, 170}},
|
||||||
|
{Region: "US Florida", ServerName: "miami408", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 42, 176}},
|
||||||
|
{Region: "US Florida", ServerName: "miami413", Protocol: "udp", PortForward: false, IP: net.IP{212, 102, 61, 37}},
|
||||||
|
{Region: "US Florida", ServerName: "miami413", Protocol: "udp", PortForward: false, IP: net.IP{212, 102, 61, 57}},
|
||||||
|
{Region: "US Houston", ServerName: "houston408", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 139, 99}},
|
||||||
|
{Region: "US Houston", ServerName: "houston408", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 139, 110}},
|
||||||
|
{Region: "US Houston", ServerName: "houston409", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 139, 165}},
|
||||||
|
{Region: "US Houston", ServerName: "houston409", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 139, 166}},
|
||||||
|
{Region: "US Houston", ServerName: "houston415", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 142, 60}},
|
||||||
|
{Region: "US Houston", ServerName: "houston415", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 142, 57}},
|
||||||
|
{Region: "US Houston", ServerName: "houston416", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 142, 105}},
|
||||||
|
{Region: "US Houston", ServerName: "houston416", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 142, 107}},
|
||||||
|
{Region: "US Houston", ServerName: "houston418", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 154, 208}},
|
||||||
|
{Region: "US Houston", ServerName: "houston418", Protocol: "udp", PortForward: false, IP: net.IP{205, 251, 154, 205}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas401", Protocol: "udp", PortForward: false, IP: net.IP{173, 239, 226, 38}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas401", Protocol: "udp", PortForward: false, IP: net.IP{173, 239, 226, 38}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas402", Protocol: "udp", PortForward: false, IP: net.IP{45, 89, 173, 180}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas402", Protocol: "udp", PortForward: false, IP: net.IP{45, 89, 173, 179}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas405", Protocol: "udp", PortForward: false, IP: net.IP{82, 102, 31, 105}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas405", Protocol: "udp", PortForward: false, IP: net.IP{82, 102, 31, 108}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas406", Protocol: "udp", PortForward: false, IP: net.IP{82, 102, 31, 188}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas406", Protocol: "udp", PortForward: false, IP: net.IP{82, 102, 31, 183}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas410", Protocol: "udp", PortForward: false, IP: net.IP{79, 110, 53, 247}},
|
||||||
|
{Region: "US Las Vegas", ServerName: "lasvegas410", Protocol: "udp", PortForward: false, IP: net.IP{79, 110, 53, 243}},
|
||||||
|
{Region: "US New York", ServerName: "newjersey414", Protocol: "udp", PortForward: false, IP: net.IP{138, 199, 10, 47}},
|
||||||
|
{Region: "US New York", ServerName: "newjersey414", Protocol: "udp", PortForward: false, IP: net.IP{138, 199, 10, 30}},
|
||||||
|
{Region: "US New York", ServerName: "newyork404", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 44, 238}},
|
||||||
|
{Region: "US New York", ServerName: "newyork404", Protocol: "udp", PortForward: false, IP: net.IP{143, 244, 44, 208}},
|
||||||
|
{Region: "US New York", ServerName: "newyork409", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 55, 244}},
|
||||||
|
{Region: "US New York", ServerName: "newyork409", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 55, 244}},
|
||||||
|
{Region: "US New York", ServerName: "newyork413", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 54, 30}},
|
||||||
|
{Region: "US New York", ServerName: "newyork413", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 54, 39}},
|
||||||
|
{Region: "US New York", ServerName: "newyork420", Protocol: "udp", PortForward: false, IP: net.IP{138, 199, 10, 83}},
|
||||||
|
{Region: "US New York", ServerName: "newyork420", Protocol: "udp", PortForward: false, IP: net.IP{138, 199, 10, 67}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle406", Protocol: "udp", PortForward: false, IP: net.IP{154, 9, 128, 66}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle406", Protocol: "udp", PortForward: false, IP: net.IP{154, 9, 128, 65}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle413", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 20, 56}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle413", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 20, 40}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle417", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 20, 163}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle417", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 20, 170}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle418", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 20, 196}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle418", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 20, 213}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle423", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 48, 175}},
|
||||||
|
{Region: "US Seattle", ServerName: "seattle423", Protocol: "udp", PortForward: false, IP: net.IP{156, 146, 48, 193}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley403", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 212, 98}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley403", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 212, 98}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley407", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 212, 203}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley407", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 212, 203}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley414", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 216, 33}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley414", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 216, 26}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley415", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 216, 53}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley415", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 216, 93}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley417", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 216, 165}},
|
||||||
|
{Region: "US Silicon Valley", ServerName: "siliconvalley417", Protocol: "udp", PortForward: false, IP: net.IP{154, 21, 216, 159}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas404", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 251, 49}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas404", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 251, 36}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas405", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 251, 79}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas405", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 251, 65}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas407", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 251, 149}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas407", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 251, 155}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas414", Protocol: "udp", PortForward: false, IP: net.IP{154, 29, 131, 229}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas414", Protocol: "udp", PortForward: false, IP: net.IP{154, 29, 131, 229}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas417", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 250, 99}},
|
||||||
|
{Region: "US Texas", ServerName: "dallas417", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 250, 103}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington435", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 44, 126}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington435", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 44, 126}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington436", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 44, 147}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington436", Protocol: "udp", PortForward: false, IP: net.IP{154, 3, 44, 149}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington440", Protocol: "udp", PortForward: false, IP: net.IP{38, 70, 11, 10}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington440", Protocol: "udp", PortForward: false, IP: net.IP{38, 70, 11, 27}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington444", Protocol: "udp", PortForward: false, IP: net.IP{38, 70, 11, 157}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington444", Protocol: "udp", PortForward: false, IP: net.IP{38, 70, 11, 147}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington445", Protocol: "udp", PortForward: false, IP: net.IP{38, 70, 11, 190}},
|
||||||
|
{Region: "US Washington DC", ServerName: "washington445", Protocol: "udp", PortForward: false, IP: net.IP{38, 70, 11, 164}},
|
||||||
|
{Region: "US West", ServerName: "phoenix406", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 241, 49}},
|
||||||
|
{Region: "US West", ServerName: "phoenix406", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 241, 6}},
|
||||||
|
{Region: "US West", ServerName: "phoenix407", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 241, 76}},
|
||||||
|
{Region: "US West", ServerName: "phoenix407", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 241, 110}},
|
||||||
|
{Region: "US West", ServerName: "phoenix410", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 252, 193}},
|
||||||
|
{Region: "US West", ServerName: "phoenix410", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 252, 193}},
|
||||||
|
{Region: "US West", ServerName: "phoenix412", Protocol: "udp", PortForward: false, IP: net.IP{107, 181, 184, 210}},
|
||||||
|
{Region: "US West", ServerName: "phoenix412", Protocol: "udp", PortForward: false, IP: net.IP{107, 181, 184, 210}},
|
||||||
|
{Region: "US West", ServerName: "phoenix414", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 242, 155}},
|
||||||
|
{Region: "US West", ServerName: "phoenix414", Protocol: "udp", PortForward: false, IP: net.IP{184, 170, 242, 155}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev401", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 58}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev401", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 55}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev402", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 28}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev402", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 23}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev403", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 5}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev403", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 4}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev404", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 44}},
|
||||||
|
{Region: "Ukraine", ServerName: "kiev404", Protocol: "udp", PortForward: true, IP: net.IP{62, 149, 20, 44}},
|
||||||
|
{Region: "United Arab Emirates", ServerName: "dubai403", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 193, 153}},
|
||||||
|
{Region: "United Arab Emirates", ServerName: "dubai403", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 193, 156}},
|
||||||
|
{Region: "United Arab Emirates", ServerName: "dubai404", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 193, 173}},
|
||||||
|
{Region: "United Arab Emirates", ServerName: "dubai404", Protocol: "udp", PortForward: true, IP: net.IP{217, 138, 193, 164}},
|
||||||
|
{Region: "Venezuela", ServerName: "venezuela403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 237, 5}},
|
||||||
|
{Region: "Venezuela", ServerName: "venezuela403", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 237, 3}},
|
||||||
|
{Region: "Venezuela", ServerName: "venezuela404", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 237, 15}},
|
||||||
|
{Region: "Venezuela", ServerName: "venezuela404", Protocol: "udp", PortForward: true, IP: net.IP{95, 181, 237, 17}},
|
||||||
|
{Region: "Vietnam", ServerName: "vietnam401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 152, 70}},
|
||||||
|
{Region: "Vietnam", ServerName: "vietnam401", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 152, 77}},
|
||||||
|
{Region: "Vietnam", ServerName: "vietnam402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 152, 93}},
|
||||||
|
{Region: "Vietnam", ServerName: "vietnam402", Protocol: "udp", PortForward: true, IP: net.IP{188, 214, 152, 88}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
211
internal/constants/privado.go
Normal file
211
internal/constants/privado.go
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
PrivadoCertificate = "MIIFKDCCAxCgAwIBAgIJAMtrmqZxIV/OMA0GCSqGSIb3DQEBDQUAMBIxEDAOBgNVBAMMB1ByaXZhZG8wHhcNMjAwMTA4MjEyODQ1WhcNMzUwMTA5MjEyODQ1WjASMRAwDgYDVQQDDAdQcml2YWRvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxPwOgiwNJzZTnKIXwAB0TSu/Lu2qt2U2I8obtQjwhi/7OrfmbmYykSdro70al2XPhnwAGGdCxW6LDnp0UN/IOhD11mgBPo14f5CLkBQjSJ6VN5miPbvK746LsNZl9H8rQGvDuPo4CG9BfPZMiDRGlsMxij/jztzgT1gmuxQ7WHfFRcNzBas1dHa9hV/d3TU6/t47x4SE/ljdcCtJiu7Zn6ODKQoys3mB7Luz2ngqUJWvkqsg+E4+3eJ0M8Hlbn5TPaRJBID7DAdYo6Vs6xGCYr981ThFcmoIQ10js10yANrrfGAzd03b3TnLAgko0uQMHjliMZL6L8sWOPHxyxJI0us88SFh4UgcFyRHKHPKux7w24SxAlZUYoUcTHp9VjG5XvDKYxzgV2RdM4ulBGbQRQ3y3/CyddsyQYMvA55Ets0LfPaBvDIcct70iXijGsdvlX1du3ArGpG7Vaje/RU4nbbGT6HYRdt5YyZfof288ukMOSj20nVcmS+c/4tqsxSerRb1aq5LOi1IemSkTMeC5gCbexk+L1vl7NT/58sxjGmu5bXwnvev/lIItfi2AlITrfUSEv19iDMKkeshwn/+sFJBMWYyluP+yJ56yR+MWoXvLlSWphLDTqq19yx3BZn0P1tgbXoR0g8PTdJFcz8z3RIb7myVLYulV1oGG/3rka0CAwEAAaOBgDB+MB0GA1UdDgQWBBTFtJkZCVDuDAD6k5bJzefjJdO3DTBCBgNVHSMEOzA5gBTFtJkZCVDuDAD6k5bJzefjJdO3DaEWpBQwEjEQMA4GA1UEAwwHUHJpdmFkb4IJAMtrmqZxIV/OMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBDQUAA4ICAQB7MUSXMeBb9wlSv4sUaT1JHEwE26nlBw+TKmezfuPU5pBlY0LYr6qQZY95DHqsRJ7ByUzGUrGo17dNGXlcuNc6TAaQQEDRPo6y+LVh2TWMk15TUMI+MkqryJtCret7xGvDigKYMJgBy58HN3RAVr1B7cL9youwzLgc2Y/NcFKvnQJKeiIYAJ7g0CcnJiQvgZTS7xdwkEBXfsngmUCIG320DLPEL+Ze0HiUrxwWljMRya6i40AeH3Zu2i532xX1wV5+cjA4RJWIKg6ri/Q54iFGtZrA9/nc6y9uoQHkmz8cGyVUmJxFzMrrIICVqUtVRxLhkTMe4UzwRWTBeGgtW4tS0yq1QonAKfOyjgRw/CeY55D2UGvnAFZdTadtYXS4Alu2P9zdwoEk3fzHiVmDjqfJVr5wz9383aABUFrPI3nz6ed/Z6LZflKh1k+DUDEp8NxU4klUULWsSOKoa5zGX51G8cdHxwQLImXvtGuN5eSR8jCTgxFZhdps/xes4KkyfIz9FMYG748M+uOTgKITf4zdJ9BAyiQaOufVQZ8WjhWzWk9YHec9VqPkzpWNGkVjiRI5ewuXwZzZ164tMv2hikBXSuUCnFz37/ZNwGlDi0oBdDszCk2GxccdFHHaCSmpjU5MrdJ+5IhtTKGeTx+US2hTIVHQFIO99DmacxSYvLNcSQ=="
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrivadoHostnameChoices() (choices []string) {
|
||||||
|
servers := PrivadoServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Hostname
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrivadoServers() []models.PrivadoServer {
|
||||||
|
return []models.PrivadoServer{
|
||||||
|
{Hostname: "akl-001.vpn.privado.io", IP: net.IP{23, 254, 104, 114}},
|
||||||
|
{Hostname: "akl-002.vpn.privado.io", IP: net.IP{23, 254, 104, 120}},
|
||||||
|
{Hostname: "akl-003.vpn.privado.io", IP: net.IP{23, 254, 104, 51}},
|
||||||
|
{Hostname: "ams-001.vpn.privado.io", IP: net.IP{91, 148, 224, 10}},
|
||||||
|
{Hostname: "ams-002.vpn.privado.io", IP: net.IP{91, 148, 224, 20}},
|
||||||
|
{Hostname: "ams-003.vpn.privado.io", IP: net.IP{91, 148, 224, 30}},
|
||||||
|
{Hostname: "ams-004.vpn.privado.io", IP: net.IP{91, 148, 224, 40}},
|
||||||
|
{Hostname: "ams-005.vpn.privado.io", IP: net.IP{91, 148, 224, 50}},
|
||||||
|
{Hostname: "ams-006.vpn.privado.io", IP: net.IP{91, 148, 224, 60}},
|
||||||
|
{Hostname: "ams-007.vpn.privado.io", IP: net.IP{91, 148, 224, 70}},
|
||||||
|
{Hostname: "ams-008.vpn.privado.io", IP: net.IP{91, 148, 224, 80}},
|
||||||
|
{Hostname: "ams-009.vpn.privado.io", IP: net.IP{91, 148, 228, 10}},
|
||||||
|
{Hostname: "ams-010.vpn.privado.io", IP: net.IP{91, 148, 228, 20}},
|
||||||
|
{Hostname: "ams-011.vpn.privado.io", IP: net.IP{91, 148, 228, 30}},
|
||||||
|
{Hostname: "ams-012.vpn.privado.io", IP: net.IP{91, 148, 228, 40}},
|
||||||
|
{Hostname: "arn-001.vpn.privado.io", IP: net.IP{86, 106, 103, 67}},
|
||||||
|
{Hostname: "arn-002.vpn.privado.io", IP: net.IP{86, 106, 103, 74}},
|
||||||
|
{Hostname: "arn-003.vpn.privado.io", IP: net.IP{86, 106, 103, 81}},
|
||||||
|
{Hostname: "arn-004.vpn.privado.io", IP: net.IP{86, 106, 103, 88}},
|
||||||
|
{Hostname: "ath-001.vpn.privado.io", IP: net.IP{188, 123, 126, 61}},
|
||||||
|
{Hostname: "ath-002.vpn.privado.io", IP: net.IP{188, 123, 126, 64}},
|
||||||
|
{Hostname: "ath-003.vpn.privado.io", IP: net.IP{188, 123, 126, 68}},
|
||||||
|
{Hostname: "ath-004.vpn.privado.io", IP: net.IP{188, 123, 126, 72}},
|
||||||
|
{Hostname: "beg-001.vpn.privado.io", IP: net.IP{89, 38, 224, 19}},
|
||||||
|
{Hostname: "beg-002.vpn.privado.io", IP: net.IP{89, 38, 224, 25}},
|
||||||
|
{Hostname: "bkk-001.vpn.privado.io", IP: net.IP{119, 59, 111, 3}},
|
||||||
|
{Hostname: "bkk-002.vpn.privado.io", IP: net.IP{119, 59, 111, 11}},
|
||||||
|
{Hostname: "bom-001.vpn.privado.io", IP: net.IP{103, 26, 204, 61}},
|
||||||
|
{Hostname: "bom-002.vpn.privado.io", IP: net.IP{103, 26, 204, 70}},
|
||||||
|
{Hostname: "bru-001.vpn.privado.io", IP: net.IP{217, 138, 211, 163}},
|
||||||
|
{Hostname: "bru-002.vpn.privado.io", IP: net.IP{217, 138, 211, 170}},
|
||||||
|
{Hostname: "bru-003.vpn.privado.io", IP: net.IP{217, 138, 211, 177}},
|
||||||
|
{Hostname: "bru-004.vpn.privado.io", IP: net.IP{217, 138, 211, 184}},
|
||||||
|
{Hostname: "bts-001.vpn.privado.io", IP: net.IP{37, 120, 221, 227}},
|
||||||
|
{Hostname: "bts-002.vpn.privado.io", IP: net.IP{37, 120, 221, 233}},
|
||||||
|
{Hostname: "bud-001.vpn.privado.io", IP: net.IP{185, 128, 26, 194}},
|
||||||
|
{Hostname: "bud-002.vpn.privado.io", IP: net.IP{185, 128, 26, 200}},
|
||||||
|
{Hostname: "cdg-001.vpn.privado.io", IP: net.IP{89, 40, 183, 99}},
|
||||||
|
{Hostname: "cdg-002.vpn.privado.io", IP: net.IP{89, 40, 183, 104}},
|
||||||
|
{Hostname: "cdg-003.vpn.privado.io", IP: net.IP{89, 40, 183, 109}},
|
||||||
|
{Hostname: "cdg-004.vpn.privado.io", IP: net.IP{89, 40, 183, 114}},
|
||||||
|
{Hostname: "cph-001.vpn.privado.io", IP: net.IP{2, 58, 46, 35}},
|
||||||
|
{Hostname: "cph-002.vpn.privado.io", IP: net.IP{2, 58, 46, 42}},
|
||||||
|
{Hostname: "cph-003.vpn.privado.io", IP: net.IP{2, 58, 46, 49}},
|
||||||
|
{Hostname: "cph-004.vpn.privado.io", IP: net.IP{2, 58, 46, 56}},
|
||||||
|
{Hostname: "dca-005.vpn.privado.io", IP: net.IP{85, 12, 61, 50}},
|
||||||
|
{Hostname: "dca-006.vpn.privado.io", IP: net.IP{85, 12, 61, 60}},
|
||||||
|
{Hostname: "dca-007.vpn.privado.io", IP: net.IP{85, 12, 61, 70}},
|
||||||
|
{Hostname: "dca-008.vpn.privado.io", IP: net.IP{85, 12, 61, 80}},
|
||||||
|
{Hostname: "dca-009.vpn.privado.io", IP: net.IP{85, 12, 61, 90}},
|
||||||
|
{Hostname: "dca-010.vpn.privado.io", IP: net.IP{85, 12, 61, 100}},
|
||||||
|
{Hostname: "dca-011.vpn.privado.io", IP: net.IP{85, 12, 61, 110}},
|
||||||
|
{Hostname: "dca-012.vpn.privado.io", IP: net.IP{85, 12, 61, 120}},
|
||||||
|
{Hostname: "dca-013.vpn.privado.io", IP: net.IP{185, 247, 68, 3}},
|
||||||
|
{Hostname: "dca-014.vpn.privado.io", IP: net.IP{185, 247, 68, 14}},
|
||||||
|
{Hostname: "dfw-001.vpn.privado.io", IP: net.IP{23, 105, 32, 243}},
|
||||||
|
{Hostname: "dfw-002.vpn.privado.io", IP: net.IP{23, 105, 32, 244}},
|
||||||
|
{Hostname: "dub-001.vpn.privado.io", IP: net.IP{84, 247, 48, 227}},
|
||||||
|
{Hostname: "dub-002.vpn.privado.io", IP: net.IP{84, 247, 48, 234}},
|
||||||
|
{Hostname: "dub-003.vpn.privado.io", IP: net.IP{84, 247, 48, 241}},
|
||||||
|
{Hostname: "dub-004.vpn.privado.io", IP: net.IP{84, 247, 48, 248}},
|
||||||
|
{Hostname: "eze-001.vpn.privado.io", IP: net.IP{168, 205, 93, 211}},
|
||||||
|
{Hostname: "eze-002.vpn.privado.io", IP: net.IP{168, 205, 93, 215}},
|
||||||
|
{Hostname: "fra-001.vpn.privado.io", IP: net.IP{91, 148, 232, 10}},
|
||||||
|
{Hostname: "fra-002.vpn.privado.io", IP: net.IP{91, 148, 232, 20}},
|
||||||
|
{Hostname: "fra-003.vpn.privado.io", IP: net.IP{91, 148, 232, 30}},
|
||||||
|
{Hostname: "fra-004.vpn.privado.io", IP: net.IP{91, 148, 232, 40}},
|
||||||
|
{Hostname: "fra-005.vpn.privado.io", IP: net.IP{91, 148, 233, 7}},
|
||||||
|
{Hostname: "fra-006.vpn.privado.io", IP: net.IP{91, 148, 233, 8}},
|
||||||
|
{Hostname: "fra-007.vpn.privado.io", IP: net.IP{91, 148, 233, 9}},
|
||||||
|
{Hostname: "fra-008.vpn.privado.io", IP: net.IP{91, 148, 233, 10}},
|
||||||
|
{Hostname: "gru-001.vpn.privado.io", IP: net.IP{177, 54, 145, 193}},
|
||||||
|
{Hostname: "gru-002.vpn.privado.io", IP: net.IP{177, 54, 145, 197}},
|
||||||
|
{Hostname: "hel-001.vpn.privado.io", IP: net.IP{194, 34, 134, 219}},
|
||||||
|
{Hostname: "hel-002.vpn.privado.io", IP: net.IP{194, 34, 134, 227}},
|
||||||
|
{Hostname: "hkg-001.vpn.privado.io", IP: net.IP{209, 58, 185, 88}},
|
||||||
|
{Hostname: "hkg-002.vpn.privado.io", IP: net.IP{209, 58, 185, 97}},
|
||||||
|
{Hostname: "hkg-003.vpn.privado.io", IP: net.IP{209, 58, 185, 108}},
|
||||||
|
{Hostname: "hkg-004.vpn.privado.io", IP: net.IP{209, 58, 185, 120}},
|
||||||
|
{Hostname: "icn-001.vpn.privado.io", IP: net.IP{169, 56, 73, 146}},
|
||||||
|
{Hostname: "icn-002.vpn.privado.io", IP: net.IP{169, 56, 73, 153}},
|
||||||
|
{Hostname: "iev-001.vpn.privado.io", IP: net.IP{176, 103, 52, 40}},
|
||||||
|
{Hostname: "iev-002.vpn.privado.io", IP: net.IP{176, 103, 53, 40}},
|
||||||
|
{Hostname: "ist-001.vpn.privado.io", IP: net.IP{185, 84, 183, 3}},
|
||||||
|
{Hostname: "ist-002.vpn.privado.io", IP: net.IP{185, 84, 183, 4}},
|
||||||
|
{Hostname: "jfk-001.vpn.privado.io", IP: net.IP{217, 138, 208, 99}},
|
||||||
|
{Hostname: "jfk-002.vpn.privado.io", IP: net.IP{217, 138, 208, 106}},
|
||||||
|
{Hostname: "jfk-003.vpn.privado.io", IP: net.IP{217, 138, 208, 113}},
|
||||||
|
{Hostname: "jfk-004.vpn.privado.io", IP: net.IP{217, 138, 208, 120}},
|
||||||
|
{Hostname: "jnb-001.vpn.privado.io", IP: net.IP{172, 107, 93, 131}},
|
||||||
|
{Hostname: "jnb-002.vpn.privado.io", IP: net.IP{172, 107, 93, 137}},
|
||||||
|
{Hostname: "lax-001.vpn.privado.io", IP: net.IP{81, 171, 62, 3}},
|
||||||
|
{Hostname: "lax-002.vpn.privado.io", IP: net.IP{81, 171, 62, 13}},
|
||||||
|
{Hostname: "lax-003.vpn.privado.io", IP: net.IP{81, 171, 62, 24}},
|
||||||
|
{Hostname: "lax-004.vpn.privado.io", IP: net.IP{81, 171, 62, 34}},
|
||||||
|
{Hostname: "lax-005.vpn.privado.io", IP: net.IP{81, 171, 62, 70}},
|
||||||
|
{Hostname: "lax-006.vpn.privado.io", IP: net.IP{81, 171, 62, 80}},
|
||||||
|
{Hostname: "lax-007.vpn.privado.io", IP: net.IP{81, 171, 62, 90}},
|
||||||
|
{Hostname: "lax-008.vpn.privado.io", IP: net.IP{81, 171, 62, 100}},
|
||||||
|
{Hostname: "lax-009.vpn.privado.io", IP: net.IP{45, 152, 182, 227}},
|
||||||
|
{Hostname: "lax-010.vpn.privado.io", IP: net.IP{45, 152, 182, 234}},
|
||||||
|
{Hostname: "lax-011.vpn.privado.io", IP: net.IP{45, 152, 182, 241}},
|
||||||
|
{Hostname: "lax-012.vpn.privado.io", IP: net.IP{45, 152, 182, 248}},
|
||||||
|
{Hostname: "lis-001.vpn.privado.io", IP: net.IP{89, 26, 243, 153}},
|
||||||
|
{Hostname: "lis-002.vpn.privado.io", IP: net.IP{89, 26, 243, 154}},
|
||||||
|
{Hostname: "lon-001.vpn.privado.io", IP: net.IP{217, 138, 195, 163}},
|
||||||
|
{Hostname: "lon-002.vpn.privado.io", IP: net.IP{217, 138, 195, 168}},
|
||||||
|
{Hostname: "lon-003.vpn.privado.io", IP: net.IP{217, 138, 195, 173}},
|
||||||
|
{Hostname: "lon-004.vpn.privado.io", IP: net.IP{217, 138, 195, 178}},
|
||||||
|
{Hostname: "mad-001.vpn.privado.io", IP: net.IP{217, 138, 218, 131}},
|
||||||
|
{Hostname: "mad-002.vpn.privado.io", IP: net.IP{217, 138, 218, 138}},
|
||||||
|
{Hostname: "mad-003.vpn.privado.io", IP: net.IP{217, 138, 218, 145}},
|
||||||
|
{Hostname: "mad-004.vpn.privado.io", IP: net.IP{217, 138, 218, 152}},
|
||||||
|
{Hostname: "man-001.vpn.privado.io", IP: net.IP{217, 138, 196, 131}},
|
||||||
|
{Hostname: "man-002.vpn.privado.io", IP: net.IP{217, 138, 196, 138}},
|
||||||
|
{Hostname: "man-003.vpn.privado.io", IP: net.IP{217, 138, 196, 145}},
|
||||||
|
{Hostname: "man-004.vpn.privado.io", IP: net.IP{217, 138, 196, 152}},
|
||||||
|
{Hostname: "mex-001.vpn.privado.io", IP: net.IP{169, 57, 96, 52}},
|
||||||
|
{Hostname: "mex-002.vpn.privado.io", IP: net.IP{169, 57, 96, 57}},
|
||||||
|
{Hostname: "mia-001.vpn.privado.io", IP: net.IP{86, 106, 87, 131}},
|
||||||
|
{Hostname: "mia-002.vpn.privado.io", IP: net.IP{86, 106, 87, 136}},
|
||||||
|
{Hostname: "mia-003.vpn.privado.io", IP: net.IP{86, 106, 87, 141}},
|
||||||
|
{Hostname: "mia-004.vpn.privado.io", IP: net.IP{86, 106, 87, 146}},
|
||||||
|
{Hostname: "mxp-001.vpn.privado.io", IP: net.IP{89, 40, 182, 195}},
|
||||||
|
{Hostname: "mxp-002.vpn.privado.io", IP: net.IP{89, 40, 182, 201}},
|
||||||
|
{Hostname: "nrt-001.vpn.privado.io", IP: net.IP{217, 138, 252, 3}},
|
||||||
|
{Hostname: "nrt-002.vpn.privado.io", IP: net.IP{217, 138, 252, 10}},
|
||||||
|
{Hostname: "nrt-003.vpn.privado.io", IP: net.IP{217, 138, 252, 17}},
|
||||||
|
{Hostname: "nrt-004.vpn.privado.io", IP: net.IP{217, 138, 252, 24}},
|
||||||
|
{Hostname: "ord-001.vpn.privado.io", IP: net.IP{23, 108, 95, 129}},
|
||||||
|
{Hostname: "ord-002.vpn.privado.io", IP: net.IP{23, 108, 95, 167}},
|
||||||
|
{Hostname: "osl-001.vpn.privado.io", IP: net.IP{84, 247, 50, 115}},
|
||||||
|
{Hostname: "osl-002.vpn.privado.io", IP: net.IP{84, 247, 50, 119}},
|
||||||
|
{Hostname: "osl-003.vpn.privado.io", IP: net.IP{84, 247, 50, 123}},
|
||||||
|
{Hostname: "otp-001.vpn.privado.io", IP: net.IP{89, 46, 102, 179}},
|
||||||
|
{Hostname: "otp-002.vpn.privado.io", IP: net.IP{89, 46, 102, 185}},
|
||||||
|
{Hostname: "phx-001.vpn.privado.io", IP: net.IP{91, 148, 236, 10}},
|
||||||
|
{Hostname: "phx-002.vpn.privado.io", IP: net.IP{91, 148, 236, 20}},
|
||||||
|
{Hostname: "phx-003.vpn.privado.io", IP: net.IP{91, 148, 236, 30}},
|
||||||
|
{Hostname: "phx-004.vpn.privado.io", IP: net.IP{91, 148, 236, 40}},
|
||||||
|
{Hostname: "phx-005.vpn.privado.io", IP: net.IP{91, 148, 236, 50}},
|
||||||
|
{Hostname: "phx-006.vpn.privado.io", IP: net.IP{91, 148, 236, 60}},
|
||||||
|
{Hostname: "phx-007.vpn.privado.io", IP: net.IP{91, 148, 236, 70}},
|
||||||
|
{Hostname: "phx-008.vpn.privado.io", IP: net.IP{91, 148, 236, 80}},
|
||||||
|
{Hostname: "prg-001.vpn.privado.io", IP: net.IP{185, 216, 35, 99}},
|
||||||
|
{Hostname: "prg-002.vpn.privado.io", IP: net.IP{185, 216, 35, 105}},
|
||||||
|
{Hostname: "rix-001.vpn.privado.io", IP: net.IP{109, 248, 149, 35}},
|
||||||
|
{Hostname: "rix-002.vpn.privado.io", IP: net.IP{109, 248, 149, 40}},
|
||||||
|
{Hostname: "rkv-001.vpn.privado.io", IP: net.IP{82, 221, 131, 78}},
|
||||||
|
{Hostname: "rkv-002.vpn.privado.io", IP: net.IP{82, 221, 131, 127}},
|
||||||
|
{Hostname: "sea-001.vpn.privado.io", IP: net.IP{23, 81, 208, 96}},
|
||||||
|
{Hostname: "sea-002.vpn.privado.io", IP: net.IP{23, 81, 208, 104}},
|
||||||
|
{Hostname: "sin-001.vpn.privado.io", IP: net.IP{92, 119, 178, 131}},
|
||||||
|
{Hostname: "sin-002.vpn.privado.io", IP: net.IP{92, 119, 178, 138}},
|
||||||
|
{Hostname: "sin-003.vpn.privado.io", IP: net.IP{92, 119, 178, 145}},
|
||||||
|
{Hostname: "sin-004.vpn.privado.io", IP: net.IP{92, 119, 178, 152}},
|
||||||
|
{Hostname: "sof-001.vpn.privado.io", IP: net.IP{217, 138, 221, 163}},
|
||||||
|
{Hostname: "sof-002.vpn.privado.io", IP: net.IP{217, 138, 221, 169}},
|
||||||
|
{Hostname: "stl-001.vpn.privado.io", IP: net.IP{148, 72, 170, 145}},
|
||||||
|
{Hostname: "stl-002.vpn.privado.io", IP: net.IP{148, 72, 172, 82}},
|
||||||
|
{Hostname: "syd-001.vpn.privado.io", IP: net.IP{93, 115, 35, 35}},
|
||||||
|
{Hostname: "syd-002.vpn.privado.io", IP: net.IP{93, 115, 35, 42}},
|
||||||
|
{Hostname: "syd-003.vpn.privado.io", IP: net.IP{93, 115, 35, 49}},
|
||||||
|
{Hostname: "syd-004.vpn.privado.io", IP: net.IP{93, 115, 35, 56}},
|
||||||
|
{Hostname: "vie-001.vpn.privado.io", IP: net.IP{5, 253, 207, 227}},
|
||||||
|
{Hostname: "vie-002.vpn.privado.io", IP: net.IP{5, 253, 207, 234}},
|
||||||
|
{Hostname: "vie-003.vpn.privado.io", IP: net.IP{5, 253, 207, 241}},
|
||||||
|
{Hostname: "vie-004.vpn.privado.io", IP: net.IP{5, 253, 207, 248}},
|
||||||
|
{Hostname: "vno-001.vpn.privado.io", IP: net.IP{185, 64, 104, 176}},
|
||||||
|
{Hostname: "vno-002.vpn.privado.io", IP: net.IP{185, 64, 104, 180}},
|
||||||
|
{Hostname: "waw-001.vpn.privado.io", IP: net.IP{217, 138, 209, 163}},
|
||||||
|
{Hostname: "waw-002.vpn.privado.io", IP: net.IP{217, 138, 209, 164}},
|
||||||
|
{Hostname: "waw-003.vpn.privado.io", IP: net.IP{217, 138, 209, 165}},
|
||||||
|
{Hostname: "waw-004.vpn.privado.io", IP: net.IP{217, 138, 209, 166}},
|
||||||
|
{Hostname: "yul-001.vpn.privado.io", IP: net.IP{217, 138, 213, 67}},
|
||||||
|
{Hostname: "yul-002.vpn.privado.io", IP: net.IP{217, 138, 213, 72}},
|
||||||
|
{Hostname: "yul-003.vpn.privado.io", IP: net.IP{217, 138, 213, 77}},
|
||||||
|
{Hostname: "yul-004.vpn.privado.io", IP: net.IP{217, 138, 213, 82}},
|
||||||
|
{Hostname: "yvr-001.vpn.privado.io", IP: net.IP{71, 19, 248, 57}},
|
||||||
|
{Hostname: "yvr-002.vpn.privado.io", IP: net.IP{71, 19, 248, 113}},
|
||||||
|
{Hostname: "yyz-003.vpn.privado.io", IP: net.IP{199, 189, 27, 19}},
|
||||||
|
{Hostname: "zrh-001.vpn.privado.io", IP: net.IP{185, 156, 175, 195}},
|
||||||
|
{Hostname: "zrh-002.vpn.privado.io", IP: net.IP{185, 156, 175, 202}},
|
||||||
|
{Hostname: "zrh-003.vpn.privado.io", IP: net.IP{185, 156, 175, 209}},
|
||||||
|
{Hostname: "zrh-004.vpn.privado.io", IP: net.IP{185, 156, 175, 216}},
|
||||||
|
}
|
||||||
|
}
|
||||||
87
internal/constants/purevpn.go
Normal file
87
internal/constants/purevpn.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
PurevpnCertificateAuthority = "MIIE6DCCA9CgAwIBAgIJAMjXFoeo5uSlMA0GCSqGSIb3DQEBCwUAMIGoMQswCQYDVQQGEwJISzEQMA4GA1UECBMHQ2VudHJhbDELMAkGA1UEBxMCSEsxGDAWBgNVBAoTD1NlY3VyZS1TZXJ2ZXJDQTELMAkGA1UECxMCSVQxGDAWBgNVBAMTD1NlY3VyZS1TZXJ2ZXJDQTEYMBYGA1UEKRMPU2VjdXJlLVNlcnZlckNBMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWluMB4XDTE2MDExNTE1MzQwOVoXDTI2MDExMjE1MzQwOVowgagxCzAJBgNVBAYTAkhLMRAwDgYDVQQIEwdDZW50cmFsMQswCQYDVQQHEwJISzEYMBYGA1UEChMPU2VjdXJlLVNlcnZlckNBMQswCQYDVQQLEwJJVDEYMBYGA1UEAxMPU2VjdXJlLVNlcnZlckNBMRgwFgYDVQQpEw9TZWN1cmUtU2VydmVyQ0ExHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDluufhyLlyvXzPUL16kAWAdivl1roQv3QHbuRshyKacf/1Er1JqEbtW3Mx9Fvr/u27qU2W8lQI6DaJhU2BfijPe/KHkib55mvHzIVvoexxya26nk79F2c+d9PnuuMdThWQO3El5a/i2AASnM7T7piIBT2WRZW2i8RbfJaTT7G7LP7OpMKIV1qyBg/cWoO7cIWQW4jmzqrNryIkF0AzStLN1DxvnQZwgXBGv0CwuAkfQuNSLu0PQgPp0PhdukNZFllv5D29IhPr0Z+kwPtrAgPQo+lHlOBHBMUpDT4XChTPeAvMaUSBsqmonAE8UUHEabWrqYN/kWNHCNkYXMkiVmK1AgMBAAGjggERMIIBDTAdBgNVHQ4EFgQU456ijsFrYnzHBShLAPpOUqQ+Z2cwgd0GA1UdIwSB1TCB0oAU456ijsFrYnzHBShLAPpOUqQ+Z2ehga6kgaswgagxCzAJBgNVBAYTAkhLMRAwDgYDVQQIEwdDZW50cmFsMQswCQYDVQQHEwJISzEYMBYGA1UEChMPU2VjdXJlLVNlcnZlckNBMQswCQYDVQQLEwJJVDEYMBYGA1UEAxMPU2VjdXJlLVNlcnZlckNBMRgwFgYDVQQpEw9TZWN1cmUtU2VydmVyQ0ExHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQDI1xaHqObkpTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvga2HMwOtUxWH/inL2qk24KX2pxLg939JNhqoyNrUpbDHag5xPQYXUmUpKrNJZ0z+o/ZnNUPHydTSXE7Z7E45J0GDN5E7g4pakndKnDLSjp03NgGsCGW+cXnz6UBPM5FStFvGdDeModeSUyoS9fjk+mYROvmiy5EiVDP91sKGcPLR7Ym0M7zl2aaqV7bb98HmMoBOxpeZQinof67nKrCsgz/xjktWFgcmPl4/PQSsmqQD0fTtWxGuRX+FzwvF2OCMCAJgp1RqJNlk2g50/kBIoJVPPCfjDFeDU5zGaWGSQ9+z1L6/z7VXdjUiHL0ouOcHwbiS4ZjTr9nMn6WdAHU2"
|
||||||
|
PurevpnCertificate = "MIIEnzCCA4egAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBqDELMAkGA1UEBhMCSEsxEDAOBgNVBAgTB0NlbnRyYWwxCzAJBgNVBAcTAkhLMRgwFgYDVQQKEw9TZWN1cmUtU2VydmVyQ0ExCzAJBgNVBAsTAklUMRgwFgYDVQQDEw9TZWN1cmUtU2VydmVyQ0ExGDAWBgNVBCkTD1NlY3VyZS1TZXJ2ZXJDQTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRvbWFpbjAeFw0xNjAxMTUxNjE1MzhaFw0yNjAxMTIxNjE1MzhaMIGdMQswCQYDVQQGEwJISzEQMA4GA1UECBMHQ2VudHJhbDELMAkGA1UEBxMCSEsxFjAUBgNVBAoTDVNlY3VyZS1DbGllbnQxCzAJBgNVBAsTAklUMRYwFAYDVQQDEw1TZWN1cmUtQ2xpZW50MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRvbWFpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxsnyn4v6xxDPnuDaYS0b9M1N8nxgg7OBPBlK+FWRxdTQ8yxt5U5CZGm7riVp7fya2J2iPZIgmHQEv/KbxztsHAVlYSfYYlalrnhEL3bDP2tY+N43AwB1k5BrPq2s1pPLT2XG951drDKG4PUuFHUP1sHzW5oQlfVCmxgIMAP8OYkCAwEAAaOCAV8wggFbMAkGA1UdEwQCMAAwLQYJYIZIAYb4QgENBCAWHkVhc3ktUlNBIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU9MwUnUDbQKKZKjoeieD2OD5NlAEwgd0GA1UdIwSB1TCB0oAU456ijsFrYnzHBShLAPpOUqQ+Z2ehga6kgaswgagxCzAJBgNVBAYTAkhLMRAwDgYDVQQIEwdDZW50cmFsMQswCQYDVQQHEwJISzEYMBYGA1UEChMPU2VjdXJlLVNlcnZlckNBMQswCQYDVQQLEwJJVDEYMBYGA1UEAxMPU2VjdXJlLVNlcnZlckNBMRgwFgYDVQQpEw9TZWN1cmUtU2VydmVyQ0ExHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQDI1xaHqObkpTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAFyFo2VUX/UFixsdPdK9/Yt6mkCWc+XS1xbapGXXb9U1d+h1iBCIV9odUHgNCXWpz1hR5Uu/OCzaZ0asLE4IFMZlQmJs8sMT0c1tfPPGW45vxbL0lhqnQ8PNcBH7huNK7VFjUh4szXRKmaQPaM4S91R3L4CaNfVeHfAg7mN2m9Zn5Gto1Q1/CFMGKu2hxwGEw5p+X1czBWEvg/O09ckx/ggkkI1NcZsNiYQ+6Pz8DdGGX3+05YwLZu94+O6iIMrzxl/il0eK83g3YPbsOrASARvw6w/8sOnJCK5eOacl21oww875KisnYdWjHB1FiI+VzQ1/gyoDsL5kPTJVuu2CoG8="
|
||||||
|
PurevpnKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMbJ8p+L+scQz57g2mEtG/TNTfJ8YIOzgTwZSvhVkcXU0PMsbeVOQmRpu64lae38mtidoj2SIJh0BL/ym8c7bBwFZWEn2GJWpa54RC92wz9rWPjeNwMAdZOQaz6trNaTy09lxvedXawyhuD1LhR1D9bB81uaEJX1QpsYCDAD/DmJAgMBAAECgYEAvTHbDupE5U0krUvHzBEIuHblptGlcfNYHoDcD3oxYR3pOGeiuElBexv+mgHVzcFLBrsQfJUlHLPfCWi3xmjRvDQcr7N7U1u7NIzazy/PpRBaKolMRiM1KMYi2DG0i4ZONwFT8bvNHOIrZzCLY54KDrqOn55OzC70WYjWh4t5evkCQQDkkzZUAeskBC9+JP/zLps8jhwfoLBWGw/zbC9ePDmX0N8MTZdcUpg6KUTf1wbkLUyVtIRjS2ao6qu1jWG6K0x3AkEA3qPWyaWQWCynhNDqu2U1cPb2kh5AJip+gqxO3emikAdajsSxeoyEC2AfyBITbeB1tvCUZH17J4i/0+OFTEQp/wJAb/zEOGJ8PzghwK8GC7JA8mk51DEZVAaMSRovFv9wxDXcoh191AjPdmdzzCuAv9iF1i8MUc3GbWoUWK39PIYsPwJAWh63sqfx5b8tj/WBDpnJKBDPfhYAoXJSA1L8GZeY1fQkE+ZKcPCwAmrGcpXeh3t0Krj3WDXyw+32uC5Apr5wwQJAPZwOOReaC4YNfBPZN9BdHvVjOYGGUffpI+X+hWpLRnQFJteAi+eqwyk0Oi0SkJB+a7jcerK2d7q7xhec5WHlng=="
|
||||||
|
PurevpnOpenvpnStaticKeyV1 = "e30af995f56d07426d9ba1f824730521d4283db4b4d0cdda9c6e8759a3799dcb7939b6a5989160c9660de0f6125cbb1f585b41c074b2fe88ecfcf17eab9a33be1352379cdf74952b588fb161a93e13df9135b2b29038231e02d657a6225705e6868ccb0c384ed11614690a1894bfbeb274cebf1fe9c2329bdd5c8a40fe8820624d2ea7540cd79ab76892db51fc371a3ac5fc9573afecb3fffe3281e61d72e91579d9b03d8cbf7909b3aebf4d90850321ee6b7d0a7846d15c27d8290e031e951e19438a4654663cad975e138f5bc5af89c737ad822f27e19057731f41e1e254cc9c95b7175c622422cde9f1f2cfd3510add94498b4d7133d3729dd214a16b27fb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PurevpnRegionChoices() (choices []string) {
|
||||||
|
servers := PurevpnServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Region
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func PurevpnCountryChoices() (choices []string) {
|
||||||
|
servers := PurevpnServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Country
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func PurevpnCityChoices() (choices []string) {
|
||||||
|
servers := PurevpnServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].City
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
// PurevpnServers returns a slice of all the server information for Purevpn.
|
||||||
|
func PurevpnServers() []models.PurevpnServer {
|
||||||
|
return []models.PurevpnServer{
|
||||||
|
{Country: "Australia", Region: "New South Wales", City: "Sydney", IPs: []net.IP{{192, 253, 241, 4}, {43, 245, 161, 84}}},
|
||||||
|
{Country: "Australia", Region: "Western Australia", City: "Perth", IPs: []net.IP{{172, 94, 123, 4}}},
|
||||||
|
{Country: "Austria", Region: "Lower Austria", City: "Langenzersdorf", IPs: []net.IP{{172, 94, 109, 4}}},
|
||||||
|
{Country: "Austria", Region: "Vienna", City: "Vienna", IPs: []net.IP{{217, 64, 127, 251}}},
|
||||||
|
{Country: "Belgium", Region: "Flanders", City: "Zaventem", IPs: []net.IP{{172, 111, 223, 4}}},
|
||||||
|
{Country: "Bulgaria", Region: "Sofia-Capital", City: "Sofia", IPs: []net.IP{{217, 138, 221, 121}}},
|
||||||
|
{Country: "Canada", Region: "Alberta", City: "Calgary", IPs: []net.IP{{172, 94, 34, 4}}},
|
||||||
|
{Country: "Canada", Region: "Ontario", City: "Toronto", IPs: []net.IP{{104, 200, 138, 196}}},
|
||||||
|
{Country: "France", Region: "Île-de-France", City: "Paris", IPs: []net.IP{{89, 40, 183, 178}}},
|
||||||
|
{Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", IPs: []net.IP{{82, 102, 16, 110}}},
|
||||||
|
{Country: "Greece", Region: "Central Macedonia", City: "Thessaloníki", IPs: []net.IP{{178, 21, 169, 244}}},
|
||||||
|
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", IPs: []net.IP{{103, 109, 103, 60}, {43, 226, 231, 4}}},
|
||||||
|
{Country: "Hong Kong", Region: "Kowloon City", City: "Kowloon", IPs: []net.IP{{36, 255, 97, 3}}},
|
||||||
|
{Country: "Italy", Region: "Trentino-Alto Adige", City: "Trento", IPs: []net.IP{{172, 111, 173, 3}}},
|
||||||
|
{Country: "Japan", Region: "Ōsaka", City: "Osaka", IPs: []net.IP{{172, 94, 56, 4}}},
|
||||||
|
{Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", IPs: []net.IP{{103, 55, 10, 133}}},
|
||||||
|
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", IPs: []net.IP{{79, 142, 64, 51}}},
|
||||||
|
{Country: "Norway", Region: "Oslo", City: "Oslo", IPs: []net.IP{{82, 102, 22, 212}}},
|
||||||
|
{Country: "Poland", Region: "Mazovia", City: "Warsaw", IPs: []net.IP{{5, 253, 206, 251}}},
|
||||||
|
{Country: "Portugal", Region: "Lisbon", City: "Lisbon", IPs: []net.IP{{5, 154, 174, 3}}},
|
||||||
|
{Country: "Russian Federation", Region: "Moscow", City: "Moscow", IPs: []net.IP{{206, 123, 139, 4}}},
|
||||||
|
{Country: "Singapore", Region: "Singapore", City: "Singapore", IPs: []net.IP{{37, 120, 208, 147}, {129, 227, 107, 242}}},
|
||||||
|
{Country: "South Africa", Region: "Gauteng", City: "Johannesburg", IPs: []net.IP{{102, 165, 3, 34}}},
|
||||||
|
{Country: "Spain", Region: "Madrid", City: "Madrid", IPs: []net.IP{{217, 138, 218, 210}}},
|
||||||
|
{Country: "Sweden", Region: "Stockholm", City: "Kista", IPs: []net.IP{{172, 111, 246, 4}}},
|
||||||
|
{Country: "Switzerland", Region: "Zurich", City: "Zürich", IPs: []net.IP{{45, 12, 222, 106}}},
|
||||||
|
{Country: "Taiwan", Region: "Taiwan", City: "Taipei", IPs: []net.IP{{128, 1, 155, 178}}},
|
||||||
|
{Country: "United Kingdom", Region: "England", City: "Birmingham", IPs: []net.IP{{188, 72, 89, 4}}},
|
||||||
|
{Country: "United Kingdom", Region: "England", City: "London", IPs: []net.IP{{193, 9, 113, 70}, {104, 37, 6, 4}, {45, 141, 154, 189}}},
|
||||||
|
{Country: "United States", Region: "Arkansas", City: "Hot Springs", IPs: []net.IP{{172, 111, 147, 4}}},
|
||||||
|
{Country: "United States", Region: "Florida", City: "Miami", IPs: []net.IP{{86, 106, 87, 178}}},
|
||||||
|
{Country: "United States", Region: "Illinois", City: "Lincolnshire", IPs: []net.IP{{141, 101, 149, 4}, {141, 101, 149, 4}, {141, 101, 149, 4}, {141, 101, 149, 4}}},
|
||||||
|
{Country: "United States", Region: "Massachusetts", City: "Newton", IPs: []net.IP{{104, 243, 244, 2}}},
|
||||||
|
{Country: "United States", Region: "New Mexico", City: "Rio Rancho", IPs: []net.IP{{104, 243, 243, 131}}},
|
||||||
|
{Country: "United States", Region: "New York", City: "New York City", IPs: []net.IP{{172, 111, 149, 4}}},
|
||||||
|
{Country: "United States", Region: "Texas", City: "Dallas", IPs: []net.IP{{172, 94, 1, 4}, {172, 94, 1, 4}, {172, 94, 1, 4}, {172, 94, 1, 4}, {172, 94, 1, 4}, {172, 94, 1, 4}, {208, 84, 155, 104}}},
|
||||||
|
{Country: "United States", Region: "Virginia", City: "Reston", IPs: []net.IP{{5, 254, 77, 27}}},
|
||||||
|
{Country: "Vietnam", Region: "Ho Chi Minh", City: "Ho Chi Minh City", IPs: []net.IP{{192, 253, 249, 132}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
55
internal/constants/servers.go
Normal file
55
internal/constants/servers.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import "github.com/qdm12/gluetun/internal/models"
|
||||||
|
|
||||||
|
func GetAllServers() (allServers models.AllServers) {
|
||||||
|
//nolint:gomnd
|
||||||
|
return models.AllServers{
|
||||||
|
Version: 1, // used for migration of the top level scheme
|
||||||
|
Cyberghost: models.CyberghostServers{
|
||||||
|
Version: 1, // model version
|
||||||
|
Timestamp: 1612031135, // latest takes precedence
|
||||||
|
Servers: CyberghostServers(),
|
||||||
|
},
|
||||||
|
Mullvad: models.MullvadServers{
|
||||||
|
Version: 1,
|
||||||
|
Timestamp: 1612031135,
|
||||||
|
Servers: MullvadServers(),
|
||||||
|
},
|
||||||
|
Nordvpn: models.NordvpnServers{
|
||||||
|
Version: 1,
|
||||||
|
Timestamp: 1611096594,
|
||||||
|
Servers: NordvpnServers(),
|
||||||
|
},
|
||||||
|
Pia: models.PiaServers{
|
||||||
|
Version: 3,
|
||||||
|
Timestamp: 1611877630,
|
||||||
|
Servers: PIAServers(),
|
||||||
|
},
|
||||||
|
Purevpn: models.PurevpnServers{
|
||||||
|
Version: 1,
|
||||||
|
Timestamp: 1612031135,
|
||||||
|
Servers: PurevpnServers(),
|
||||||
|
},
|
||||||
|
Privado: models.PrivadoServers{
|
||||||
|
Version: 2,
|
||||||
|
Timestamp: 1612031135,
|
||||||
|
Servers: PrivadoServers(),
|
||||||
|
},
|
||||||
|
Surfshark: models.SurfsharkServers{
|
||||||
|
Version: 1,
|
||||||
|
Timestamp: 1612031135,
|
||||||
|
Servers: SurfsharkServers(),
|
||||||
|
},
|
||||||
|
Vyprvpn: models.VyprvpnServers{
|
||||||
|
Version: 1,
|
||||||
|
Timestamp: 1612031135,
|
||||||
|
Servers: VyprvpnServers(),
|
||||||
|
},
|
||||||
|
Windscribe: models.WindscribeServers{
|
||||||
|
Version: 2,
|
||||||
|
Timestamp: 1612031135,
|
||||||
|
Servers: WindscribeServers(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
174
internal/constants/servers_test.go
Normal file
174
internal/constants/servers_test.go
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func digestServerModelVersion(t *testing.T, server interface{}, version uint16) string {
|
||||||
|
bytes, err := json.Marshal(server)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
bytes = append(bytes, []byte(fmt.Sprintf("%d", version))...)
|
||||||
|
arr := sha256.Sum256(bytes)
|
||||||
|
hexString := hex.EncodeToString(arr[:])
|
||||||
|
if len(hexString) > 8 {
|
||||||
|
hexString = hexString[:8]
|
||||||
|
}
|
||||||
|
return hexString
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_versions(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
allServers := GetAllServers()
|
||||||
|
const format = "you forgot to update the version for %s"
|
||||||
|
testCases := map[string]struct {
|
||||||
|
model interface{}
|
||||||
|
version uint16
|
||||||
|
digest string
|
||||||
|
}{
|
||||||
|
"Cyberghost": {
|
||||||
|
model: models.CyberghostServer{},
|
||||||
|
version: allServers.Cyberghost.Version,
|
||||||
|
digest: "fd6242bb",
|
||||||
|
},
|
||||||
|
"Mullvad": {
|
||||||
|
model: models.MullvadServer{},
|
||||||
|
version: allServers.Mullvad.Version,
|
||||||
|
digest: "665e9dc1",
|
||||||
|
},
|
||||||
|
"Nordvpn": {
|
||||||
|
model: models.NordvpnServer{},
|
||||||
|
version: allServers.Nordvpn.Version,
|
||||||
|
digest: "040de8d0",
|
||||||
|
},
|
||||||
|
"Private Internet Access": {
|
||||||
|
model: models.PIAServer{},
|
||||||
|
version: allServers.Pia.Version,
|
||||||
|
digest: "b90147aa",
|
||||||
|
},
|
||||||
|
"Privado": {
|
||||||
|
model: models.PrivadoServer{},
|
||||||
|
version: allServers.Privado.Version,
|
||||||
|
digest: "1d5aeb23",
|
||||||
|
},
|
||||||
|
"Purevpn": {
|
||||||
|
model: models.PurevpnServer{},
|
||||||
|
version: allServers.Purevpn.Version,
|
||||||
|
digest: "ada45379",
|
||||||
|
},
|
||||||
|
"Surfshark": {
|
||||||
|
model: models.SurfsharkServer{},
|
||||||
|
version: allServers.Surfshark.Version,
|
||||||
|
digest: "042bef64",
|
||||||
|
},
|
||||||
|
"Vyprvpn": {
|
||||||
|
model: models.VyprvpnServer{},
|
||||||
|
version: allServers.Vyprvpn.Version,
|
||||||
|
digest: "042bef64",
|
||||||
|
},
|
||||||
|
"Windscribe": {
|
||||||
|
model: models.WindscribeServer{},
|
||||||
|
version: allServers.Windscribe.Version,
|
||||||
|
digest: "6e3ca639",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
name := name
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
digest := digestServerModelVersion(t, testCase.model, testCase.version)
|
||||||
|
failureMessage := fmt.Sprintf(format, name)
|
||||||
|
assert.Equal(t, testCase.digest, digest, failureMessage)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func digestServersTimestamp(t *testing.T, servers interface{}, timestamp int64) string {
|
||||||
|
bytes, err := json.Marshal(servers)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
bytes = append(bytes, []byte(fmt.Sprintf("%d", timestamp))...)
|
||||||
|
arr := sha256.Sum256(bytes)
|
||||||
|
hexString := hex.EncodeToString(arr[:])
|
||||||
|
if len(hexString) > 8 {
|
||||||
|
hexString = hexString[:8]
|
||||||
|
}
|
||||||
|
return hexString
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_timestamps(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
allServers := GetAllServers()
|
||||||
|
const format = "you forgot to update the timestamp for %s"
|
||||||
|
testCases := map[string]struct {
|
||||||
|
servers interface{}
|
||||||
|
timestamp int64
|
||||||
|
digest string
|
||||||
|
}{
|
||||||
|
"Cyberghost": {
|
||||||
|
servers: allServers.Cyberghost.Servers,
|
||||||
|
timestamp: allServers.Cyberghost.Timestamp,
|
||||||
|
digest: "5d3a8cbf",
|
||||||
|
},
|
||||||
|
"Mullvad": {
|
||||||
|
servers: allServers.Mullvad.Servers,
|
||||||
|
timestamp: allServers.Mullvad.Timestamp,
|
||||||
|
digest: "e2e006cf",
|
||||||
|
},
|
||||||
|
"Nordvpn": {
|
||||||
|
servers: allServers.Nordvpn.Servers,
|
||||||
|
timestamp: allServers.Nordvpn.Timestamp,
|
||||||
|
digest: "2296312c",
|
||||||
|
},
|
||||||
|
"Private Internet Access": {
|
||||||
|
servers: allServers.Pia.Servers,
|
||||||
|
timestamp: allServers.Pia.Timestamp,
|
||||||
|
digest: "1d2938a1",
|
||||||
|
},
|
||||||
|
"Purevpn": {
|
||||||
|
servers: allServers.Purevpn.Servers,
|
||||||
|
timestamp: allServers.Purevpn.Timestamp,
|
||||||
|
digest: "cd19edf5",
|
||||||
|
},
|
||||||
|
"Privado": {
|
||||||
|
servers: allServers.Privado.Servers,
|
||||||
|
timestamp: allServers.Privado.Timestamp,
|
||||||
|
digest: "2ac55360",
|
||||||
|
},
|
||||||
|
"Surfshark": {
|
||||||
|
servers: allServers.Surfshark.Servers,
|
||||||
|
timestamp: allServers.Surfshark.Timestamp,
|
||||||
|
digest: "1a7f38bb",
|
||||||
|
},
|
||||||
|
"Vyprvpn": {
|
||||||
|
servers: allServers.Vyprvpn.Servers,
|
||||||
|
timestamp: allServers.Vyprvpn.Timestamp,
|
||||||
|
digest: "1753d4f8",
|
||||||
|
},
|
||||||
|
"Windscribe": {
|
||||||
|
servers: allServers.Windscribe.Servers,
|
||||||
|
timestamp: allServers.Windscribe.Timestamp,
|
||||||
|
digest: "4e719aa3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
name := name
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
digest := digestServersTimestamp(t, testCase.servers, testCase.timestamp)
|
||||||
|
failureMessage := fmt.Sprintf(format, name)
|
||||||
|
assert.Equal(t, testCase.digest, digest, failureMessage)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Annoucement is a message annoucement
|
// Announcement is a message announcement.
|
||||||
Annoucement = "Total rewrite in Go with many new features"
|
Announcement = "New Docker image qmcgaw/gluetun"
|
||||||
// AnnoucementExpiration is the expiration time of the annoucement in unix timestamp
|
// AnnouncementExpiration is the expiration date of the announcement in format yyyy-mm-dd.
|
||||||
AnnoucementExpiration = 1582761600
|
AnnouncementExpiration = "2021-01-20"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// IssueLink is the link for users to use to create issues
|
// IssueLink is the link for users to use to create issues.
|
||||||
IssueLink = "https://github.com/qdm12/private-internet-access-docker/issues/new"
|
IssueLink = "https://github.com/qdm12/gluetun/issues/new"
|
||||||
)
|
)
|
||||||
|
|||||||
17
internal/constants/splash_test.go
Normal file
17
internal/constants/splash_test.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_AnnouncementExpiration(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if len(AnnouncementExpiration) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err := time.Parse("2006-01-02", AnnouncementExpiration)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
14
internal/constants/status.go
Normal file
14
internal/constants/status.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Starting models.LoopStatus = "starting"
|
||||||
|
Running models.LoopStatus = "running"
|
||||||
|
Stopping models.LoopStatus = "stopping"
|
||||||
|
Stopped models.LoopStatus = "stopped"
|
||||||
|
Crashed models.LoopStatus = "crashed"
|
||||||
|
Completed models.LoopStatus = "completed"
|
||||||
|
)
|
||||||
164
internal/constants/surfshark.go
Normal file
164
internal/constants/surfshark.go
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
SurfsharkCertificate = "MIIFTTCCAzWgAwIBAgIJAMs9S3fqwv+mMA0GCSqGSIb3DQEBCwUAMD0xCzAJBgNVBAYTAlZHMRIwEAYDVQQKDAlTdXJmc2hhcmsxGjAYBgNVBAMMEVN1cmZzaGFyayBSb290IENBMB4XDTE4MDMxNDA4NTkyM1oXDTI4MDMxMTA4NTkyM1owPTELMAkGA1UEBhMCVkcxEjAQBgNVBAoMCVN1cmZzaGFyazEaMBgGA1UEAwwRU3VyZnNoYXJrIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDEGMNj0aisM63oSkmVJyZPaYX7aPsZtzsxo6m6p5Wta3MGASoryRsBuRaH6VVa0fwbI1nw5ubyxkuaNa4v3zHVwuSq6F1p8S811+1YP1av+jqDcMyojH0ujZSHIcb/i5LtaHNXBQ3qN48Cc7sqBnTIIFpmb5HthQ/4pW+a82b1guM5dZHsh7q+LKQDIGmvtMtO1+NEnmj81BApFayiaD1ggvwDI4x7o/Y3ksfWSCHnqXGyqzSFLh8QuQrTmWUm84YHGFxoI1/8AKdIyVoB6BjcaMKtKs/pbctk6vkzmYf0XmGovDKPQF6MwUekchLjB5gSBNnptSQ9kNgnTLqi0OpSwI6ixX52Ksva6UM8P01ZIhWZ6ua/T/tArgODy5JZMW+pQ1A6L0b7egIeghpwKnPRG+5CzgO0J5UE6gv000mqbmC3CbiS8xi2xuNgruAyY2hUOoV9/BuBev8ttE5ZCsJH3YlG6NtbZ9hPc61GiBSx8NJnX5QHyCnfic/X87eST/amZsZCAOJ5v4EPSaKrItt+HrEFWZQIq4fJmHJNNbYvWzCE08AL+5/6Z+lxb/Bm3dapx2zdit3x2e+miGHekuiE8lQWD0rXD4+T+nDRi3X+kyt8Ex/8qRiUfrisrSHFzVMRungIMGdO9O/zCINFrb7wahm4PqU2f12Z9TRCOTXciQIDAQABo1AwTjAdBgNVHQ4EFgQUYRpbQwyDahLMN3F2ony3+UqOYOgwHwYDVR0jBBgwFoAUYRpbQwyDahLMN3F2ony3+UqOYOgwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAn9zV7F/XVnFNZhHFrt0ZS1Yqz+qM9CojLmiyblMFh0p7t+Hh+VKVgMwrz0LwDH4UsOosXA28eJPmech6/bjfymkoXISy/NUSTFpUChGO9RabGGxJsT4dugOw9MPaIVZffny4qYOc/rXDXDSfF2b+303lLPI43y9qoe0oyZ1vtk/UKG75FkWfFUogGNbpOkuz+et5Y0aIEiyg0yh6/l5Q5h8+yom0HZnREHhqieGbkaGKLkyu7zQ4D4tRK/mBhd8nv+09GtPEG+D5LPbabFVxKjBMP4Vp24WuSUOqcGSsURHevawPVBfgmsxf1UCjelaIwngdh6WfNCRXa5QQPQTKubQvkvXONCDdhmdXQccnRX1nJWhPYi0onffvjsWUfztRypsKzX4dvM9k7xnIcGSGEnCC4RCgt1UiZIj7frcCMssbA6vJ9naM0s7JF7N3VKeHJtqe1OCRHMYnWUZt9vrqX6IoIHlZCoLlv39wFW9QNxelcAOCVbD+19MZ0ZXt7LitjIqe7yF5WxDQN4xru087FzQ4Hfj7eH1SNLLyKZkA1eecjmRoi/OoqAt7afSnwtQLtMUc2bQDg6rHt5C0e4dCLqP/9PGZTSJiwmtRHJ/N5qYWIh9ju83APvLm/AGBTR2pXmj9G3KdVOkpIC7L35dI623cSEC3Q3UZutsEm/UplsM="
|
||||||
|
SurfsharkOpenvpnStaticKeyV1 = "b02cb1d7c6fee5d4f89b8de72b51a8d0c7b282631d6fc19be1df6ebae9e2779e6d9f097058a31c97f57f0c35526a44ae09a01d1284b50b954d9246725a1ead1ff224a102ed9ab3da0152a15525643b2eee226c37041dc55539d475183b889a10e18bb94f079a4a49888da566b99783460ece01daaf93548beea6c827d9674897e7279ff1a19cb092659e8c1860fbad0db4ad0ad5732f1af4655dbd66214e552f04ed8fd0104e1d4bf99c249ac229ce169d9ba22068c6c0ab742424760911d4636aafb4b85f0c952a9ce4275bc821391aa65fcd0d2394f006e3fba0fd34c4bc4ab260f4b45dec3285875589c97d3087c9134d3a3aa2f904512e85aa2dc2202498"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SurfsharkRegionChoices() (choices []string) {
|
||||||
|
servers := SurfsharkServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Region
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
// SurfsharkServers returns a slice of all the server information for Surfshark.
|
||||||
|
func SurfsharkServers() []models.SurfsharkServer {
|
||||||
|
return []models.SurfsharkServer{
|
||||||
|
{Region: "Albania", IPs: []net.IP{{31, 171, 153, 99}, {31, 171, 153, 131}, {31, 171, 154, 101}, {31, 171, 154, 149}, {31, 171, 154, 163}, {31, 171, 154, 165}}},
|
||||||
|
{Region: "Argentina Buenos Aires", IPs: []net.IP{{91, 206, 168, 9}, {91, 206, 168, 13}, {91, 206, 168, 21}, {91, 206, 168, 31}, {91, 206, 168, 41}, {91, 206, 168, 45}, {91, 206, 168, 54}, {91, 206, 168, 62}}},
|
||||||
|
{Region: "Australia Melbourne", IPs: []net.IP{{103, 192, 80, 11}, {103, 192, 80, 147}, {103, 192, 80, 227}, {144, 48, 38, 139}, {144, 48, 38, 149}, {144, 48, 38, 181}}},
|
||||||
|
{Region: "Australia Perth", IPs: []net.IP{{45, 248, 78, 43}, {124, 150, 139, 27}, {124, 150, 139, 35}, {124, 150, 139, 123}, {124, 150, 139, 125}, {124, 150, 139, 179}}},
|
||||||
|
{Region: "Australia Sydney", IPs: []net.IP{{45, 125, 247, 45}, {180, 149, 228, 115}, {180, 149, 228, 149}, {180, 149, 228, 165}, {180, 149, 228, 171}, {180, 149, 228, 173}}},
|
||||||
|
{Region: "Austria", IPs: []net.IP{{5, 253, 207, 85}, {37, 120, 212, 133}, {37, 120, 212, 139}, {89, 187, 168, 44}, {89, 187, 168, 46}, {89, 187, 168, 54}, {89, 187, 168, 56}}},
|
||||||
|
{Region: "Belgium", IPs: []net.IP{{5, 253, 205, 99}, {5, 253, 205, 101}, {37, 120, 218, 29}, {89, 249, 73, 197}, {91, 90, 123, 149}, {91, 90, 123, 173}, {91, 90, 123, 213}, {185, 104, 186, 77}}},
|
||||||
|
{Region: "Brazil", IPs: []net.IP{{45, 231, 207, 72}, {191, 96, 13, 39}, {191, 96, 13, 41}, {191, 96, 13, 43}, {191, 96, 73, 210}, {191, 96, 73, 214}, {191, 96, 73, 216}, {191, 96, 73, 228}, {191, 96, 73, 232}}},
|
||||||
|
{Region: "Bulgaria", IPs: []net.IP{{37, 120, 152, 37}, {37, 120, 152, 195}, {217, 138, 202, 19}, {217, 138, 202, 21}}},
|
||||||
|
{Region: "Canada Montreal", IPs: []net.IP{{172, 98, 82, 243}, {198, 8, 85, 5}, {198, 8, 85, 69}, {198, 8, 85, 72}, {198, 8, 85, 89}, {198, 8, 85, 163}}},
|
||||||
|
{Region: "Canada Toronto", IPs: []net.IP{{68, 71, 244, 131}, {68, 71, 244, 197}, {68, 71, 244, 212}, {68, 71, 244, 220}, {104, 200, 138, 147}, {104, 200, 138, 154}}},
|
||||||
|
{Region: "Canada Toronto mp001", IPs: []net.IP{{138, 197, 151, 26}}},
|
||||||
|
{Region: "Chile", IPs: []net.IP{{31, 169, 121, 3}, {31, 169, 121, 5}}},
|
||||||
|
{Region: "Colombia", IPs: []net.IP{{45, 129, 32, 3}, {45, 129, 32, 8}, {45, 129, 32, 20}, {45, 129, 32, 22}, {45, 129, 32, 27}, {45, 129, 32, 29}, {45, 129, 32, 32}, {45, 129, 32, 38}}},
|
||||||
|
{Region: "Costa Rica", IPs: []net.IP{{176, 227, 241, 24}, {176, 227, 241, 26}, {176, 227, 241, 29}, {176, 227, 241, 31}, {176, 227, 241, 33}, {176, 227, 241, 35}}},
|
||||||
|
{Region: "Croatia", IPs: []net.IP{{85, 10, 51, 89}, {85, 10, 51, 91}, {89, 164, 99, 111}, {89, 164, 99, 134}, {89, 164, 99, 136}}},
|
||||||
|
{Region: "Cyprus", IPs: []net.IP{{195, 47, 194, 36}, {195, 47, 194, 54}, {195, 47, 194, 56}, {195, 47, 194, 59}, {195, 47, 194, 61}, {195, 47, 194, 64}, {195, 47, 194, 66}, {195, 47, 194, 70}}},
|
||||||
|
{Region: "Czech Republic", IPs: []net.IP{{185, 180, 14, 149}, {193, 9, 112, 181}, {217, 138, 199, 179}, {217, 138, 220, 133}, {217, 138, 220, 149}, {217, 138, 220, 163}}},
|
||||||
|
{Region: "Estonia", IPs: []net.IP{{165, 231, 163, 21}, {185, 174, 159, 51}, {185, 174, 159, 53}, {185, 174, 159, 67}}},
|
||||||
|
{Region: "Finland", IPs: []net.IP{{196, 244, 191, 43}, {196, 244, 191, 91}, {196, 244, 191, 101}, {196, 244, 191, 165}}},
|
||||||
|
{Region: "France Bordeaux", IPs: []net.IP{{185, 108, 106, 26}, {185, 108, 106, 69}, {185, 108, 106, 102}, {185, 108, 106, 106}, {185, 108, 106, 180}, {185, 108, 106, 186}}},
|
||||||
|
{Region: "France Marseilles", IPs: []net.IP{{185, 166, 84, 19}, {185, 166, 84, 29}, {185, 166, 84, 51}, {185, 166, 84, 55}, {185, 166, 84, 57}, {185, 166, 84, 61}, {185, 166, 84, 63}, {185, 166, 84, 83}}},
|
||||||
|
{Region: "France Paris", IPs: []net.IP{{45, 89, 174, 61}, {84, 17, 60, 250}, {84, 247, 51, 253}, {143, 244, 56, 232}, {143, 244, 57, 101}, {143, 244, 57, 103}}},
|
||||||
|
{Region: "Germany Berlin", IPs: []net.IP{{37, 120, 217, 179}, {193, 29, 106, 21}, {193, 29, 106, 83}, {193, 29, 106, 149}, {193, 29, 106, 187}, {217, 138, 216, 219}}},
|
||||||
|
{Region: "Germany Frankfurt am Main", IPs: []net.IP{{37, 120, 197, 13}, {89, 187, 169, 104}, {138, 199, 19, 132}, {138, 199, 19, 147}, {138, 199, 19, 157}, {138, 199, 19, 190}, {156, 146, 33, 73}, {156, 146, 33, 87}}},
|
||||||
|
{Region: "Germany Frankfurt am Main st001", IPs: []net.IP{{45, 87, 212, 179}}},
|
||||||
|
{Region: "Germany Frankfurt am Main st002", IPs: []net.IP{{45, 87, 212, 181}}},
|
||||||
|
{Region: "Germany Frankfurt am Main st003", IPs: []net.IP{{45, 87, 212, 183}}},
|
||||||
|
{Region: "Germany Frankfurt am Main st004", IPs: []net.IP{{195, 181, 174, 226}}},
|
||||||
|
{Region: "Germany Frankfurt am Main st005", IPs: []net.IP{{195, 181, 174, 228}}},
|
||||||
|
{Region: "Germany Frankfurt mp001", IPs: []net.IP{{46, 101, 189, 14}}},
|
||||||
|
{Region: "Germany Munich", IPs: []net.IP{{79, 143, 191, 141}, {79, 143, 191, 231}, {178, 238, 231, 53}, {178, 238, 231, 55}}},
|
||||||
|
{Region: "Germany Nuremberg", IPs: []net.IP{{62, 171, 149, 162}, {62, 171, 151, 154}, {62, 171, 151, 156}, {62, 171, 151, 158}, {62, 171, 151, 160}, {95, 111, 253, 65}, {144, 91, 123, 50}, {144, 91, 123, 52}}},
|
||||||
|
{Region: "Germany Singapour", IPs: []net.IP{{159, 89, 14, 157}}},
|
||||||
|
{Region: "Greece", IPs: []net.IP{{194, 150, 167, 28}, {194, 150, 167, 32}, {194, 150, 167, 38}, {194, 150, 167, 40}, {194, 150, 167, 44}, {194, 150, 167, 48}}},
|
||||||
|
{Region: "Hong Kong", IPs: []net.IP{{84, 17, 37, 156}, {84, 17, 57, 66}, {84, 17, 57, 71}, {212, 102, 42, 194}, {212, 102, 42, 196}, {212, 102, 42, 211}}},
|
||||||
|
{Region: "Iceland", IPs: []net.IP{{82, 221, 128, 156}, {82, 221, 128, 169}, {82, 221, 143, 62}, {82, 221, 143, 64}, {82, 221, 143, 69}, {82, 221, 143, 71}}},
|
||||||
|
{Region: "India Chennai", IPs: []net.IP{{103, 94, 27, 99}, {103, 94, 27, 101}, {103, 94, 27, 115}, {103, 94, 27, 227}, {103, 108, 117, 147}}},
|
||||||
|
{Region: "India Indore", IPs: []net.IP{{103, 39, 132, 187}, {103, 39, 132, 189}, {103, 39, 134, 59}, {103, 39, 134, 61}, {137, 59, 52, 107}, {137, 59, 52, 109}}},
|
||||||
|
{Region: "Indonesia", IPs: []net.IP{{103, 120, 66, 214}, {103, 120, 66, 216}, {103, 120, 66, 221}, {103, 120, 66, 227}}},
|
||||||
|
{Region: "Ireland", IPs: []net.IP{{5, 157, 13, 67}, {5, 157, 13, 91}, {5, 157, 13, 93}, {5, 157, 13, 107}, {5, 157, 13, 117}, {5, 157, 13, 133}, {185, 108, 128, 161}, {217, 138, 222, 43}}},
|
||||||
|
{Region: "Israel", IPs: []net.IP{{87, 239, 255, 111}, {87, 239, 255, 114}, {87, 239, 255, 116}, {87, 239, 255, 121}}},
|
||||||
|
{Region: "Italy Milan", IPs: []net.IP{{37, 120, 201, 71}, {45, 9, 251, 167}, {84, 17, 58, 134}, {84, 17, 58, 146}, {212, 102, 54, 152}, {212, 102, 54, 167}, {212, 102, 54, 170}, {212, 102, 54, 177}}},
|
||||||
|
{Region: "Italy Rome", IPs: []net.IP{{82, 102, 26, 115}, {87, 101, 94, 213}, {185, 217, 71, 21}, {185, 217, 71, 51}, {185, 217, 71, 213}, {185, 217, 71, 243}, {217, 138, 219, 237}, {217, 138, 219, 253}}},
|
||||||
|
{Region: "Japan Tokyo", IPs: []net.IP{{45, 87, 213, 87}, {45, 87, 213, 103}, {84, 17, 34, 26}, {89, 187, 161, 4}, {89, 187, 161, 241}, {138, 199, 22, 130}}},
|
||||||
|
{Region: "Japan Tokyo st001", IPs: []net.IP{{45, 87, 213, 19}}},
|
||||||
|
{Region: "Japan Tokyo st002", IPs: []net.IP{{45, 87, 213, 21}}},
|
||||||
|
{Region: "Japan Tokyo st003", IPs: []net.IP{{45, 87, 213, 23}}},
|
||||||
|
{Region: "Japan Tokyo st004", IPs: []net.IP{{217, 138, 212, 19}}},
|
||||||
|
{Region: "Japan Tokyo st005", IPs: []net.IP{{217, 138, 212, 21}}},
|
||||||
|
{Region: "Japan Tokyo st006", IPs: []net.IP{{82, 102, 28, 123}}},
|
||||||
|
{Region: "Japan Tokyo st007", IPs: []net.IP{{82, 102, 28, 125}}},
|
||||||
|
{Region: "Japan Tokyo st008", IPs: []net.IP{{89, 187, 161, 12}}},
|
||||||
|
{Region: "Japan Tokyo st009", IPs: []net.IP{{89, 187, 161, 14}}},
|
||||||
|
{Region: "Japan Tokyo st010", IPs: []net.IP{{89, 187, 161, 17}}},
|
||||||
|
{Region: "Japan Tokyo st011", IPs: []net.IP{{89, 187, 161, 19}}},
|
||||||
|
{Region: "Japan Tokyo st012", IPs: []net.IP{{89, 187, 161, 7}}},
|
||||||
|
{Region: "Japan Tokyo st013", IPs: []net.IP{{89, 187, 161, 9}}},
|
||||||
|
{Region: "Kazakhstan", IPs: []net.IP{{95, 57, 207, 200}}},
|
||||||
|
{Region: "Korea", IPs: []net.IP{{45, 130, 137, 3}, {45, 130, 137, 10}, {45, 130, 137, 16}, {45, 130, 137, 26}, {45, 130, 137, 32}, {45, 130, 137, 46}, {45, 130, 137, 48}, {45, 130, 137, 50}}},
|
||||||
|
{Region: "Latvia", IPs: []net.IP{{188, 92, 78, 140}, {188, 92, 78, 142}, {188, 92, 78, 145}, {188, 92, 78, 150}}},
|
||||||
|
{Region: "Luxembourg", IPs: []net.IP{{185, 153, 151, 73}, {185, 153, 151, 80}, {185, 153, 151, 98}, {185, 153, 151, 100}, {185, 153, 151, 116}, {185, 153, 151, 118}, {185, 153, 151, 126}, {185, 153, 151, 160}}},
|
||||||
|
{Region: "Malaysia", IPs: []net.IP{{42, 0, 30, 158}, {42, 0, 30, 164}, {42, 0, 30, 179}, {42, 0, 30, 181}, {42, 0, 30, 183}, {42, 0, 30, 209}}},
|
||||||
|
{Region: "Mexico City Mexico", IPs: []net.IP{{194, 41, 112, 14}, {194, 41, 112, 30}, {194, 41, 112, 33}, {194, 41, 112, 35}, {194, 41, 112, 37}, {194, 41, 112, 39}}},
|
||||||
|
{Region: "Moldova", IPs: []net.IP{{178, 175, 128, 235}, {178, 175, 128, 237}}},
|
||||||
|
{Region: "Netherlands Amsterdam", IPs: []net.IP{{81, 19, 208, 56}, {81, 19, 209, 59}, {89, 46, 223, 54}, {89, 46, 223, 60}, {89, 46, 223, 84}, {143, 244, 42, 74}, {178, 239, 173, 51}, {212, 102, 35, 216}}},
|
||||||
|
{Region: "Netherlands Amsterdam mp001", IPs: []net.IP{{188, 166, 43, 117}}},
|
||||||
|
{Region: "Nigeria", IPs: []net.IP{{102, 165, 23, 4}, {102, 165, 23, 6}, {102, 165, 23, 42}, {102, 165, 23, 44}}},
|
||||||
|
{Region: "North Macedonia", IPs: []net.IP{{185, 225, 28, 67}, {185, 225, 28, 83}, {185, 225, 28, 91}, {185, 225, 28, 99}, {185, 225, 28, 101}, {185, 225, 28, 107}, {185, 225, 28, 109}, {185, 225, 28, 245}}},
|
||||||
|
{Region: "Norway", IPs: []net.IP{{45, 12, 223, 197}, {45, 12, 223, 213}, {84, 247, 50, 27}, {84, 247, 50, 29}, {91, 219, 215, 53}, {91, 219, 215, 69}, {95, 174, 66, 37}, {95, 174, 66, 41}}},
|
||||||
|
{Region: "Paraguay", IPs: []net.IP{{181, 40, 18, 47}, {181, 40, 18, 59}, {186, 16, 32, 163}, {186, 16, 32, 168}, {186, 16, 32, 173}}},
|
||||||
|
{Region: "Philippines", IPs: []net.IP{{45, 134, 224, 3}, {45, 134, 224, 8}, {45, 134, 224, 18}, {45, 134, 224, 20}}},
|
||||||
|
{Region: "Poland Gdansk", IPs: []net.IP{{5, 133, 14, 198}, {5, 187, 49, 147}, {5, 187, 53, 53}, {5, 187, 53, 55}, {178, 255, 44, 69}, {178, 255, 45, 187}}},
|
||||||
|
{Region: "Poland Warsaw", IPs: []net.IP{{5, 253, 206, 67}, {5, 253, 206, 71}, {5, 253, 206, 227}, {5, 253, 206, 229}, {84, 17, 55, 132}, {84, 17, 55, 134}, {185, 246, 208, 77}, {185, 246, 208, 105}}},
|
||||||
|
{Region: "Portugal Loule", IPs: []net.IP{{176, 61, 146, 97}, {176, 61, 146, 108}, {176, 61, 146, 113}, {176, 61, 146, 118}}},
|
||||||
|
{Region: "Portugal Porto", IPs: []net.IP{{194, 39, 127, 171}, {194, 39, 127, 191}, {194, 39, 127, 193}, {194, 39, 127, 231}, {194, 39, 127, 233}, {194, 39, 127, 240}, {194, 39, 127, 244}}},
|
||||||
|
{Region: "Romania", IPs: []net.IP{{45, 89, 175, 55}, {86, 106, 137, 147}, {185, 102, 217, 157}, {185, 102, 217, 159}, {185, 102, 217, 167}, {185, 102, 217, 169}, {185, 102, 217, 194}, {185, 102, 217, 196}}},
|
||||||
|
{Region: "Russia St. Petersburg", IPs: []net.IP{{185, 246, 88, 66}, {185, 246, 88, 118}}},
|
||||||
|
{Region: "Serbia", IPs: []net.IP{{37, 120, 193, 51}, {152, 89, 160, 213}, {152, 89, 160, 215}}},
|
||||||
|
{Region: "Singapore", IPs: []net.IP{{89, 187, 162, 184}, {89, 187, 162, 186}, {89, 187, 163, 130}, {89, 187, 163, 134}, {89, 187, 163, 136}, {89, 187, 163, 195}, {89, 187, 163, 197}, {89, 187, 163, 207}}},
|
||||||
|
{Region: "Singapore in", IPs: []net.IP{{128, 199, 193, 35}}},
|
||||||
|
{Region: "Singapore mp001", IPs: []net.IP{{206, 189, 94, 229}}},
|
||||||
|
{Region: "Singapore st001", IPs: []net.IP{{217, 138, 201, 91}}},
|
||||||
|
{Region: "Singapore st002", IPs: []net.IP{{217, 138, 201, 93}}},
|
||||||
|
{Region: "Singapore st003", IPs: []net.IP{{84, 247, 49, 19}}},
|
||||||
|
{Region: "Singapore st004", IPs: []net.IP{{84, 247, 49, 21}}},
|
||||||
|
{Region: "Slovekia", IPs: []net.IP{{37, 120, 221, 3}, {185, 76, 8, 210}, {185, 76, 8, 212}, {185, 76, 8, 215}, {185, 76, 8, 217}, {193, 37, 255, 35}, {193, 37, 255, 37}, {193, 37, 255, 39}}},
|
||||||
|
{Region: "Slovenia", IPs: []net.IP{{195, 158, 249, 36}, {195, 158, 249, 38}, {195, 158, 249, 40}, {195, 158, 249, 46}}},
|
||||||
|
{Region: "South Africa", IPs: []net.IP{{102, 165, 47, 132}, {154, 16, 93, 51}, {154, 16, 93, 53}, {154, 127, 49, 230}, {154, 127, 49, 232}, {154, 127, 50, 138}}},
|
||||||
|
{Region: "Spain Barcelona", IPs: []net.IP{{37, 120, 142, 179}, {37, 120, 142, 181}, {185, 188, 61, 7}, {185, 188, 61, 23}, {185, 188, 61, 37}, {185, 188, 61, 41}}},
|
||||||
|
{Region: "Spain Madrid", IPs: []net.IP{{37, 120, 148, 229}, {89, 37, 95, 11}, {89, 37, 95, 27}, {188, 208, 141, 18}, {188, 208, 141, 100}, {212, 102, 48, 4}, {212, 102, 48, 18}, {212, 102, 48, 20}}},
|
||||||
|
{Region: "Spain Valencia", IPs: []net.IP{{196, 196, 150, 67}, {196, 196, 150, 71}, {196, 196, 150, 83}, {196, 196, 150, 85}}},
|
||||||
|
{Region: "Sweden", IPs: []net.IP{{185, 76, 9, 34}, {185, 76, 9, 39}, {185, 76, 9, 41}, {185, 76, 9, 51}, {185, 76, 9, 55}, {185, 76, 9, 57}}},
|
||||||
|
{Region: "Switzerland", IPs: []net.IP{{45, 12, 222, 243}, {84, 17, 53, 86}, {84, 17, 53, 166}, {84, 17, 53, 210}, {84, 17, 53, 219}, {84, 17, 53, 223}, {156, 146, 62, 41}, {156, 146, 62, 56}}},
|
||||||
|
{Region: "Taiwan", IPs: []net.IP{{2, 58, 242, 43}, {2, 58, 242, 157}, {103, 152, 151, 5}, {103, 152, 151, 19}, {103, 152, 151, 69}, {103, 152, 151, 83}}},
|
||||||
|
{Region: "Turkey Istanbul", IPs: []net.IP{{107, 150, 95, 149}, {107, 150, 95, 157}, {107, 150, 95, 163}, {107, 150, 95, 165}}},
|
||||||
|
{Region: "UK Glasgow", IPs: []net.IP{{185, 108, 105, 5}, {185, 108, 105, 7}, {185, 108, 105, 38}, {185, 108, 105, 151}, {185, 108, 105, 153}, {185, 108, 105, 170}, {185, 108, 105, 174}, {185, 108, 105, 182}}},
|
||||||
|
{Region: "UK London", IPs: []net.IP{{37, 10, 114, 70}, {89, 35, 29, 71}, {185, 16, 206, 116}, {185, 44, 76, 55}, {185, 44, 78, 90}, {185, 114, 224, 119}, {185, 141, 206, 182}, {188, 240, 71, 179}}},
|
||||||
|
{Region: "UK London mp001", IPs: []net.IP{{206, 189, 119, 92}}},
|
||||||
|
{Region: "UK London st001", IPs: []net.IP{{217, 146, 82, 83}}},
|
||||||
|
{Region: "UK London st002", IPs: []net.IP{{185, 134, 22, 80}}},
|
||||||
|
{Region: "UK London st003", IPs: []net.IP{{185, 134, 22, 92}}},
|
||||||
|
{Region: "UK London st004", IPs: []net.IP{{185, 44, 76, 186}}},
|
||||||
|
{Region: "UK London st005", IPs: []net.IP{{185, 44, 76, 188}}},
|
||||||
|
{Region: "UK Manchester", IPs: []net.IP{{37, 120, 200, 5}, {37, 120, 200, 117}, {89, 238, 130, 235}, {91, 90, 121, 131}, {91, 90, 121, 149}, {194, 37, 98, 37}, {194, 37, 98, 219}, {217, 138, 196, 3}}},
|
||||||
|
{Region: "US Bend", IPs: []net.IP{{45, 43, 14, 73}, {45, 43, 14, 75}, {45, 43, 14, 85}, {45, 43, 14, 93}, {45, 43, 14, 95}, {45, 43, 14, 105}, {154, 16, 168, 186}}},
|
||||||
|
{Region: "US Boston", IPs: []net.IP{{173, 237, 207, 32}, {173, 237, 207, 42}, {173, 237, 207, 60}, {192, 34, 83, 230}, {192, 34, 83, 236}, {199, 217, 107, 20}}},
|
||||||
|
{Region: "US Charlotte", IPs: []net.IP{{154, 16, 171, 195}, {154, 16, 171, 197}, {154, 16, 171, 206}, {155, 254, 29, 165}, {155, 254, 31, 182}, {192, 154, 253, 67}, {192, 154, 254, 135}}},
|
||||||
|
{Region: "US Chicago", IPs: []net.IP{{74, 119, 146, 181}, {107, 152, 100, 26}, {143, 244, 60, 167}, {143, 244, 60, 169}, {184, 170, 250, 72}, {184, 170, 250, 154}}},
|
||||||
|
{Region: "US Dallas", IPs: []net.IP{{66, 115, 177, 133}, {66, 115, 177, 138}, {66, 115, 177, 146}, {66, 115, 177, 151}, {66, 115, 177, 153}, {66, 115, 177, 156}, {89, 187, 175, 165}, {212, 102, 40, 76}}},
|
||||||
|
{Region: "US Denver", IPs: []net.IP{{174, 128, 245, 149}, {212, 102, 44, 68}, {212, 102, 44, 71}, {212, 102, 44, 83}, {212, 102, 44, 91}, {212, 102, 44, 98}}},
|
||||||
|
{Region: "US Gahanna", IPs: []net.IP{{104, 244, 208, 37}, {104, 244, 208, 107}, {104, 244, 209, 53}, {104, 244, 209, 101}, {104, 244, 210, 115}, {104, 244, 211, 141}}},
|
||||||
|
{Region: "US Houston", IPs: []net.IP{{104, 148, 30, 37}, {104, 148, 30, 83}, {199, 10, 64, 67}, {199, 10, 64, 69}, {199, 10, 64, 99}, {199, 10, 64, 179}}},
|
||||||
|
{Region: "US Kansas City", IPs: []net.IP{{63, 141, 236, 243}, {63, 141, 236, 245}, {69, 30, 249, 123}, {173, 208, 149, 197}, {173, 208, 202, 59}, {173, 208, 202, 61}, {198, 204, 231, 147}, {198, 204, 231, 149}}},
|
||||||
|
{Region: "US Las Vegas", IPs: []net.IP{{45, 89, 173, 203}, {79, 110, 54, 125}, {79, 110, 54, 131}, {89, 187, 187, 147}, {89, 187, 187, 149}, {185, 242, 5, 155}, {185, 242, 5, 211}, {185, 242, 5, 213}}},
|
||||||
|
{Region: "US Latham", IPs: []net.IP{{45, 43, 19, 74}, {45, 43, 19, 84}, {45, 43, 19, 90}, {154, 16, 169, 3}, {154, 16, 169, 7}}},
|
||||||
|
{Region: "US Los Angeles", IPs: []net.IP{{84, 17, 45, 249}, {138, 199, 9, 193}, {138, 199, 9, 199}, {138, 199, 9, 209}, {172, 83, 44, 83}, {184, 170, 243, 215}, {192, 111, 134, 69}, {192, 111, 134, 202}}},
|
||||||
|
{Region: "US Miami", IPs: []net.IP{{89, 187, 173, 201}, {107, 181, 164, 211}, {172, 83, 42, 3}, {172, 83, 42, 5}, {172, 83, 42, 55}, {172, 83, 42, 141}}},
|
||||||
|
{Region: "US New York City", IPs: []net.IP{{84, 17, 35, 71}, {84, 17, 35, 86}, {138, 199, 40, 169}, {138, 199, 40, 179}, {172, 98, 75, 35}, {192, 40, 59, 227}, {192, 40, 59, 240}, {199, 36, 221, 85}}},
|
||||||
|
{Region: "US New York City mp001", IPs: []net.IP{{45, 55, 60, 159}}},
|
||||||
|
{Region: "US New York City st001", IPs: []net.IP{{92, 119, 177, 19}}},
|
||||||
|
{Region: "US New York City st002", IPs: []net.IP{{92, 119, 177, 21}}},
|
||||||
|
{Region: "US New York City st003", IPs: []net.IP{{92, 119, 177, 23}}},
|
||||||
|
{Region: "US New York City st004", IPs: []net.IP{{193, 148, 18, 51}}},
|
||||||
|
{Region: "US New York City st005", IPs: []net.IP{{193, 148, 18, 53}}},
|
||||||
|
{Region: "US Orlando", IPs: []net.IP{{66, 115, 182, 74}, {198, 147, 22, 83}, {198, 147, 22, 85}, {198, 147, 22, 87}, {198, 147, 22, 131}, {198, 147, 22, 147}, {198, 147, 22, 163}, {198, 147, 22, 211}}},
|
||||||
|
{Region: "US Phoenix", IPs: []net.IP{{107, 181, 184, 117}, {199, 58, 187, 3}, {199, 58, 187, 5}, {199, 58, 187, 8}, {199, 58, 187, 15}, {199, 58, 187, 69}}},
|
||||||
|
{Region: "US Saint Louis", IPs: []net.IP{{148, 72, 169, 209}, {148, 72, 169, 211}, {148, 72, 169, 213}, {148, 72, 174, 36}, {148, 72, 174, 38}, {148, 72, 174, 48}}},
|
||||||
|
{Region: "US Salt Lake City", IPs: []net.IP{{104, 200, 131, 165}, {104, 200, 131, 167}, {104, 200, 131, 172}, {104, 200, 131, 229}, {104, 200, 131, 233}, {104, 200, 131, 245}}},
|
||||||
|
{Region: "US San Francisco", IPs: []net.IP{{107, 181, 166, 55}, {185, 124, 240, 143}, {185, 124, 240, 151}, {185, 124, 240, 161}, {185, 124, 240, 173}, {198, 8, 81, 37}}},
|
||||||
|
{Region: "US San Francisco mp001", IPs: []net.IP{{165, 232, 53, 25}}},
|
||||||
|
{Region: "US Tampa", IPs: []net.IP{{209, 216, 92, 200}, {209, 216, 92, 205}, {209, 216, 92, 210}, {209, 216, 92, 215}, {209, 216, 92, 220}, {209, 216, 92, 227}}},
|
||||||
|
{Region: "Ukraine", IPs: []net.IP{{45, 9, 238, 23}, {45, 9, 238, 38}, {176, 107, 185, 71}, {176, 107, 185, 73}}},
|
||||||
|
{Region: "United Arab Emirates", IPs: []net.IP{{45, 9, 249, 243}, {45, 9, 249, 247}, {45, 9, 250, 101}, {176, 125, 231, 5}, {176, 125, 231, 13}, {176, 125, 231, 27}}},
|
||||||
|
{Region: "Vietnam", IPs: []net.IP{{202, 143, 110, 29}, {202, 143, 110, 36}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package constants
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// TinyProxyInfoLevel is the info log level for TinyProxy
|
|
||||||
TinyProxyInfoLevel models.TinyProxyLogLevel = "Info"
|
|
||||||
// TinyProxyConnectLevel is the info log level for TinyProxy
|
|
||||||
TinyProxyConnectLevel models.TinyProxyLogLevel = "Connect"
|
|
||||||
// TinyProxyNoticeLevel is the info log level for TinyProxy
|
|
||||||
TinyProxyNoticeLevel models.TinyProxyLogLevel = "Notice"
|
|
||||||
// TinyProxyWarnLevel is the warning log level for TinyProxy
|
|
||||||
TinyProxyWarnLevel models.TinyProxyLogLevel = "Warning"
|
|
||||||
// TinyProxyErrorLevel is the error log level for TinyProxy
|
|
||||||
TinyProxyErrorLevel models.TinyProxyLogLevel = "Error"
|
|
||||||
// TinyProxyCriticalLevel is the critical log level for TinyProxy
|
|
||||||
TinyProxyCriticalLevel models.TinyProxyLogLevel = "Critical"
|
|
||||||
)
|
|
||||||
@@ -1,21 +1,29 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
import (
|
const (
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
// PrivateInternetAccess is a VPN provider.
|
||||||
)
|
PrivateInternetAccess = "private internet access"
|
||||||
|
// Mullvad is a VPN provider.
|
||||||
const (
|
Mullvad = "mullvad"
|
||||||
// PrivateInternetAccess is a VPN provider
|
// Windscribe is a VPN provider.
|
||||||
PrivateInternetAccess models.VPNProvider = "private internet access"
|
Windscribe = "windscribe"
|
||||||
// Mullvad is a VPN provider
|
// Surfshark is a VPN provider.
|
||||||
Mullvad models.VPNProvider = "mullvad"
|
Surfshark = "surfshark"
|
||||||
// Windscribe is a VPN provider
|
// Cyberghost is a VPN provider.
|
||||||
Windscribe models.VPNProvider = "windscribe"
|
Cyberghost = "cyberghost"
|
||||||
)
|
// Vyprvpn is a VPN provider.
|
||||||
|
Vyprvpn = "vyprvpn"
|
||||||
const (
|
// NordVPN is a VPN provider.
|
||||||
// TCP is a network protocol (reliable and slower than UDP)
|
Nordvpn = "nordvpn"
|
||||||
TCP models.NetworkProtocol = "tcp"
|
// PureVPN is a VPN provider.
|
||||||
// UDP is a network protocol (unreliable and faster than TCP)
|
Purevpn = "purevpn"
|
||||||
UDP models.NetworkProtocol = "udp"
|
// Privado is a VPN provider.
|
||||||
)
|
Privado = "privado"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TCP is a network protocol (reliable and slower than UDP).
|
||||||
|
TCP string = "tcp"
|
||||||
|
// UDP is a network protocol (unreliable and faster than TCP).
|
||||||
|
UDP string = "udp"
|
||||||
|
)
|
||||||
|
|||||||
99
internal/constants/vyprvpn.go
Normal file
99
internal/constants/vyprvpn.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
VyprvpnCertificate = "MIIGDjCCA/agAwIBAgIJAL2ON5xbane/MA0GCSqGSIb3DQEBDQUAMIGTMQswCQYDVQQGEwJDSDEQMA4GA1UECAwHTHVjZXJuZTEPMA0GA1UEBwwGTWVnZ2VuMRkwFwYDVQQKDBBHb2xkZW4gRnJvZyBHbWJIMSEwHwYDVQQDDBhHb2xkZW4gRnJvZyBHbWJIIFJvb3QgQ0ExIzAhBgkqhkiG9w0BCQEWFGFkbWluQGdvbGRlbmZyb2cuY29tMB4XDTE5MTAxNzIwMTQxMFoXDTM5MTAxMjIwMTQxMFowgZMxCzAJBgNVBAYTAkNIMRAwDgYDVQQIDAdMdWNlcm5lMQ8wDQYDVQQHDAZNZWdnZW4xGTAXBgNVBAoMEEdvbGRlbiBGcm9nIEdtYkgxITAfBgNVBAMMGEdvbGRlbiBGcm9nIEdtYkggUm9vdCBDQTEjMCEGCSqGSIb3DQEJARYUYWRtaW5AZ29sZGVuZnJvZy5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCtuddaZrpWZ+nUuJpG+ohTquO3XZtq6d4U0E2oiPeIiwm+WWLY49G+GNJb5aVrlrBojaykCAc2sU6NeUlpg3zuqrDqLcz7PAE4OdNiOdrLBF1o9ZHrcITDZN304eAY5nbyHx5V6x/QoDVCi4g+5OVTA+tZjpcl4wRIpgknWznO73IKCJ6YckpLn1BsFrVCb2ehHYZLg7Js58FzMySIxBmtkuPeHQXL61DFHh3cTFcMxqJjzh7EGsWRyXfbAaBGYnT+TZwzpLXXt8oBGpNXG8YBDrPdK0A+lzMnJ4nS0rgHDSRF0brx+QYk/6CgM510uFzB7zytw9UTD3/5TvKlCUmTGGgI84DbJ3DEvjxbgiQnJXCUZKKYSHwrK79Y4Qn+lXu4Bu0ZTCJBje0GUVMTPAvBCeDvzSe0iRcVSNMJVM68d4kD1PpSY/zWfCz5hiOjHWuXinaoZ0JJqRF8kGbJsbDlDYDtVvh/Cd4aWN6Q/2XLpszBsG5i8sdkS37nzkdlRwNEIZwsKfcXwdTOlDinR1LUG68LmzJAwfNE47xbrZUsdGGfG+HSPsrqFFiLGe7Y4e2+a7vGdSY9qR9PAzyx0ijCCrYzZDIsb2dwjLctUx6a3LNV8cpfhKX+s6tfMldGufPI7byHT1Ybf0NtMS1d1RjD6IbqedXQdCKtaw68kTX//wIDAQABo2MwYTAdBgNVHQ4EFgQU2EbQvBd1r/EADr2jCPMXsH7zEXEwHwYDVR0jBBgwFoAU2EbQvBd1r/EADr2jCPMXsH7zEXEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQENBQADggIBAAViCPieIronV+9asjZyo5oSZSNWUkWRYdezjezsf49+fwT12iRgnkSEQeoj5caqcOfNm/eRpN4G7jhhCcxy9RGF+GurIlZ4v0mChZbx1jcxqr9/3/Z2TqvHALyWngBYDv6pv1iWcd9a4+QL9kj1Tlp8vUDIcHMtDQkEHnkhC+MnjyrdsdNE5wjlLljjFR2Qy5a6/kWwZ1JQVYof1J1EzY6mU7YLMHOdjfmeci5i0vg8+9kGMsc/7Wm69L1BeqpDB3ZEAgmOtda2jwOevJ4sABmRoSThFp4DeMcxb62HW1zZCCpgzWv/33+pZdPvnZHSz7RGoxH4Ln7eBf3oo2PMlu7wCsid3HUdgkRf2Og1RJIrFfEjb7jga1JbKX2Qo/FH3txzdUimKiDRv3ccFmEOqjndUG6hP+7/EsI43oCPYOvZR+u5GdOkhYrDGZlvjXeJ1CpQxTR/EX+Vt7F8YG+i2LkO7lhPLb+LzgPAxVPCcEMHruuUlE1BYxxzRMOW4X4kjHvJjZGISxa9lgTY3e0mnoQNQVBHKfzI2vGLwvcrFcCIrVxeEbj2dryfByyhZlrNPFbXyf7P4OSfk+fVh6Is1IF1wksfLY/6gWvcmXB8JwmKFDa9s5NfzXnzP3VMrNUWXN3G8Eee6qzKKTDsJ70OrgAx9j9a+dMLfe1vP5t6GQj5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VyprvpnRegionChoices() (choices []string) {
|
||||||
|
servers := VyprvpnServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Region
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func VyprvpnServers() []models.VyprvpnServer {
|
||||||
|
return []models.VyprvpnServer{
|
||||||
|
{Region: "Algeria", IPs: []net.IP{{209, 99, 75, 20}}},
|
||||||
|
{Region: "Argentina", IPs: []net.IP{{209, 99, 109, 19}}},
|
||||||
|
{Region: "Australia Melbourne", IPs: []net.IP{{209, 99, 117, 19}}},
|
||||||
|
{Region: "Australia Perth", IPs: []net.IP{{209, 99, 1, 19}}},
|
||||||
|
{Region: "Australia Sydney", IPs: []net.IP{{209, 99, 117, 18}}},
|
||||||
|
{Region: "Austria", IPs: []net.IP{{128, 90, 96, 18}}},
|
||||||
|
{Region: "Bahrain", IPs: []net.IP{{209, 99, 115, 19}}},
|
||||||
|
{Region: "Belgium", IPs: []net.IP{{128, 90, 96, 20}}},
|
||||||
|
{Region: "Brazil", IPs: []net.IP{{209, 99, 109, 20}}},
|
||||||
|
{Region: "Bulgaria", IPs: []net.IP{{128, 90, 96, 22}}},
|
||||||
|
{Region: "Canada", IPs: []net.IP{{209, 99, 21, 18}}},
|
||||||
|
{Region: "Columbia", IPs: []net.IP{{209, 99, 109, 21}}},
|
||||||
|
{Region: "Costa Rica", IPs: []net.IP{{209, 99, 109, 22}}},
|
||||||
|
{Region: "Czech Republic", IPs: []net.IP{{128, 90, 96, 24}}},
|
||||||
|
{Region: "Denmark", IPs: []net.IP{{128, 90, 96, 28}}},
|
||||||
|
{Region: "Dubai", IPs: []net.IP{{128, 90, 45, 104}}},
|
||||||
|
{Region: "Egypt", IPs: []net.IP{{209, 99, 75, 21}}},
|
||||||
|
{Region: "El Salvador", IPs: []net.IP{{209, 99, 61, 20}}},
|
||||||
|
{Region: "Finland", IPs: []net.IP{{128, 90, 96, 32}}},
|
||||||
|
{Region: "France", IPs: []net.IP{{128, 90, 96, 34}}},
|
||||||
|
{Region: "Germany", IPs: []net.IP{{128, 90, 96, 26}}},
|
||||||
|
{Region: "Greece", IPs: []net.IP{{209, 99, 75, 22}}},
|
||||||
|
{Region: "Hong Kong", IPs: []net.IP{{128, 90, 227, 18}}},
|
||||||
|
{Region: "Iceland", IPs: []net.IP{{209, 99, 22, 20}}},
|
||||||
|
{Region: "India", IPs: []net.IP{{209, 99, 115, 20}}},
|
||||||
|
{Region: "Indonesia", IPs: []net.IP{{209, 99, 1, 20}}},
|
||||||
|
{Region: "Ireland", IPs: []net.IP{{209, 99, 22, 19}}},
|
||||||
|
{Region: "Israel", IPs: []net.IP{{209, 99, 75, 18}}},
|
||||||
|
{Region: "Italy", IPs: []net.IP{{128, 90, 96, 36}}},
|
||||||
|
{Region: "Japan", IPs: []net.IP{{209, 99, 113, 18}}},
|
||||||
|
{Region: "Latvia", IPs: []net.IP{{128, 90, 96, 44}}},
|
||||||
|
{Region: "Liechtenstein", IPs: []net.IP{{128, 90, 96, 38}}},
|
||||||
|
{Region: "Lithuania", IPs: []net.IP{{128, 90, 96, 40}}},
|
||||||
|
{Region: "Luxembourg", IPs: []net.IP{{128, 90, 96, 42}}},
|
||||||
|
{Region: "Macao", IPs: []net.IP{{128, 90, 227, 36}}},
|
||||||
|
{Region: "Malaysia", IPs: []net.IP{{209, 99, 1, 21}}},
|
||||||
|
{Region: "Maldives", IPs: []net.IP{{209, 99, 1, 26}}},
|
||||||
|
{Region: "Marshall Islands", IPs: []net.IP{{209, 99, 1, 25}}},
|
||||||
|
{Region: "Mexico", IPs: []net.IP{{209, 99, 61, 19}}},
|
||||||
|
{Region: "Netherlands", IPs: []net.IP{{128, 90, 96, 16}}},
|
||||||
|
{Region: "New Zealand", IPs: []net.IP{{209, 99, 117, 20}}},
|
||||||
|
{Region: "Norway", IPs: []net.IP{{128, 90, 96, 46}}},
|
||||||
|
{Region: "Pakistan", IPs: []net.IP{{209, 99, 75, 23}}},
|
||||||
|
{Region: "Panama", IPs: []net.IP{{209, 99, 109, 23}}},
|
||||||
|
{Region: "Philippines", IPs: []net.IP{{209, 99, 1, 22}}},
|
||||||
|
{Region: "Poland", IPs: []net.IP{{128, 90, 96, 48}}},
|
||||||
|
{Region: "Portugal", IPs: []net.IP{{128, 90, 96, 50}}},
|
||||||
|
{Region: "Qatar", IPs: []net.IP{{209, 99, 115, 21}}},
|
||||||
|
{Region: "Romania", IPs: []net.IP{{128, 90, 96, 52}}},
|
||||||
|
{Region: "Russia", IPs: []net.IP{{128, 90, 96, 54}}},
|
||||||
|
{Region: "Saudi Arabia", IPs: []net.IP{{209, 99, 115, 22}}},
|
||||||
|
{Region: "Singapore", IPs: []net.IP{{209, 99, 1, 18}}},
|
||||||
|
{Region: "Slovakia", IPs: []net.IP{{128, 90, 96, 60}}},
|
||||||
|
{Region: "Slovenia", IPs: []net.IP{{128, 90, 96, 58}}},
|
||||||
|
{Region: "South Korea", IPs: []net.IP{{209, 99, 113, 19}}},
|
||||||
|
{Region: "Spain", IPs: []net.IP{{128, 90, 96, 30}}},
|
||||||
|
{Region: "Sweden", IPs: []net.IP{{128, 90, 96, 56}}},
|
||||||
|
{Region: "Switzerland", IPs: []net.IP{{209, 99, 60, 18}}},
|
||||||
|
{Region: "Taiwan", IPs: []net.IP{{128, 90, 227, 27}}},
|
||||||
|
{Region: "Thailand", IPs: []net.IP{{209, 99, 1, 23}}},
|
||||||
|
{Region: "Turkey", IPs: []net.IP{{128, 90, 96, 62}}},
|
||||||
|
{Region: "USA Austin", IPs: []net.IP{{209, 99, 61, 18}}},
|
||||||
|
{Region: "USA Chicago", IPs: []net.IP{{209, 99, 93, 18}}},
|
||||||
|
{Region: "USA Los Angeles", IPs: []net.IP{{209, 99, 67, 18}}},
|
||||||
|
{Region: "USA Miami", IPs: []net.IP{{209, 99, 109, 18}}},
|
||||||
|
{Region: "USA New York", IPs: []net.IP{{209, 99, 63, 18}}},
|
||||||
|
{Region: "USA San Francisco", IPs: []net.IP{{209, 99, 95, 18}}},
|
||||||
|
{Region: "USA Seattle", IPs: []net.IP{{209, 99, 94, 18}}},
|
||||||
|
{Region: "USA Washington DC", IPs: []net.IP{{209, 99, 62, 18}}},
|
||||||
|
{Region: "Ukraine", IPs: []net.IP{{128, 90, 96, 64}}},
|
||||||
|
{Region: "United Kingdom", IPs: []net.IP{{209, 99, 22, 18}}},
|
||||||
|
{Region: "Uruguay", IPs: []net.IP{{209, 99, 61, 21}}},
|
||||||
|
{Region: "Vietnam", IPs: []net.IP{{209, 99, 1, 24}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
341
internal/constants/windscribe.go
Normal file
341
internal/constants/windscribe.go
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
//nolint:lll
|
||||||
|
const (
|
||||||
|
WindscribeCertificate = "MIIF3DCCA8SgAwIBAgIJAMsOivWTmu9fMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkNBMQswCQYDVQQIDAJPTjEQMA4GA1UEBwwHVG9yb250bzEbMBkGA1UECgwSV2luZHNjcmliZSBMaW1pdGVkMRMwEQYDVQQLDApPcGVyYXRpb25zMRswGQYDVQQDDBJXaW5kc2NyaWJlIE5vZGUgQ0EwHhcNMTYwMzA5MDMyNjIwWhcNNDAxMDI5MDMyNjIwWjB7MQswCQYDVQQGEwJDQTELMAkGA1UECAwCT04xEDAOBgNVBAcMB1Rvcm9udG8xGzAZBgNVBAoMEldpbmRzY3JpYmUgTGltaXRlZDETMBEGA1UECwwKT3BlcmF0aW9uczEbMBkGA1UEAwwSV2luZHNjcmliZSBOb2RlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAruBtLR1Vufd71LeQEqChgHS4AQJ0fSRner0gmZPEr2TL5uWboOEWXFFoEUTthF+P/N8yy3xRZ8HhG/zKlmJ1xw+7KZRbTADD6shJPj3/uvTIO80sU+9LmsyKSWuPhQ1NkgNA7rrMTfz9eHJ2MVDs4XCpYWyX9iuAQrHSY6aPq+4TpCbUgprkM3Gwjh9RSt9IoDoc4CF2bWSaVepUcL9yz/SXLPzFx2OT9rFrDhL3ryHRzJQ/tA+VD8A7lo8bhOcDqiXgEFmVOZNMLw+r167Qq1Ck7X86yr2mnW/6HK2gJOvY0/SPKukfGJAiYZKdG+fe4ekyYcAVhDfPJg7rF9wUqPwUzejJyAs1K18JwX94Y8fnD6vQobjpC3qfHtwQP7Uj2AcI6QC8ytWDegV6UIkHXAMXBQSX5suSQoE11deG32cy7nyp5vhgy31rTyNoopqlcCAhPm6k0jVVQbvXhLcpTSL8iCCoMdrP28i/xsfvktBAkl5giHMdK6hxqWgPI+Bx9uPIhRp3fJ2z8AgFm8g1ARB2ZzQ+OZZ2RUIkJuUKhi2kUhgKSAQ+eF89aoqDjp/J1miZqGRzt4DovSZfQOeL01RkKHEibAPYCfgHG2ZSwoLoeaxE2vNZiX4dpXiOQYTOIXOwEPZzPvfTQf9T4Kxvx3jzQnt3PzjlMCqKk3Aipm8CAwEAAaNjMGEwHQYDVR0OBBYEFEH2v9F2z938Ebngsj9RkVSSgs45MB8GA1UdIwQYMBaAFEH2v9F2z938Ebngsj9RkVSSgs45MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAgI6NgYkVo5rB6yKStgHjjZsINsgEvoMuHwkM0YaV22XtKNiHdsiOmY/PGCRemFobTEHk5XHcvcOTWv/D1qVf8fI21WAoNQVH7h8KEsr4uMGKCB6Lu8l6xALXRMjo1xb6JKBWXwIAzUu691rUD2exT1E+A5t+xw+gzqV8rWTMIoUaH7O1EKjN6ryGW71Khiik8/ETrP3YT32ZbS2P902iMKw9rpmuS0wWhnO5k/iO/6YNA1ZMV5JG5oZvZQYEDk7enLD9HvqazofMuy/Sz/n62ZCDdQsnabzxl04wwv5Y3JZbV/6bOM520GgdJEoDxviY05ax2Mz05otyBzrAVjFw9RZt/Ls8ATifu9BusZ2ootvscdIuE3x+ZCl5lvANcFEnvgGw0qpCeASLpsfxwq1dRgIn7BOiTauFv4eoeFAQvCD+l+EKGWKu3M2y19DgYX94N2+Xs2bwChroaO5e4iFemMLMuWKZvYgnqS9OAtRSYWbNX/wliiPz7u13yj+qSWgMfu8WPYNQlMZJXuGWUvKLEXCUExlu7/o8D4HpsVs30E0pUdaqN0vExB1KegxPWWrmLcYnPG3knXpkC3ZBZ5P/el/2eyhZRy9ydiITF8gM3L08E8aeqvzZMw2FDSmousydIzlXgeS5VuEf+lUFA2h8oZYGQgrLt+ot8MbLhJlkp4Q=="
|
||||||
|
WindscribeOpenvpnStaticKeyV1 = "5801926a57ac2ce27e3dfd1dd6ef82042d82bd4f3f0021296f57734f6f1ea714a6623845541c4b0c3dea0a050fe6746cb66dfab14cda27e5ae09d7c155aa554f399fa4a863f0e8c1af787e5c602a801d3a2ec41e395a978d56729457fe6102d7d9e9119aa83643210b33c678f9d4109e3154ac9c759e490cb309b319cf708cae83ddadc3060a7a26564d1a24411cd552fe6620ea16b755697a4fc5e6e9d0cfc0c5c4a1874685429046a424c026db672e4c2c492898052ba59128d46200b40f880027a8b6610a4d559bdc9346d33a0a6b08e75c7fd43192b162bfd0aef0c716b31584827693f676f9a5047123466f0654eade34972586b31c6ce7e395f4b478cb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WindscribeRegionChoices() (choices []string) {
|
||||||
|
servers := WindscribeServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Region
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func WindscribeCityChoices() (choices []string) {
|
||||||
|
servers := WindscribeServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].City
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func WindscribeHostnameChoices() (choices []string) {
|
||||||
|
servers := WindscribeServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Hostname
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func WindscribeServers() []models.WindscribeServer {
|
||||||
|
return []models.WindscribeServer{
|
||||||
|
{Region: "Albania", City: "Tirana", Hostname: "al-002.whiskergalaxy.com", IP: net.IP{31, 171, 152, 179}},
|
||||||
|
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-008.whiskergalaxy.com", IP: net.IP{190, 103, 176, 147}},
|
||||||
|
{Region: "Australia", City: "Adelaide ", Hostname: "au-011.whiskergalaxy.com", IP: net.IP{103, 108, 92, 83}},
|
||||||
|
{Region: "Australia", City: "Adelaide", Hostname: "au-008.whiskergalaxy.com", IP: net.IP{116, 90, 72, 243}},
|
||||||
|
{Region: "Australia", City: "Brisbane", Hostname: "au-007.whiskergalaxy.com", IP: net.IP{103, 62, 50, 208}},
|
||||||
|
{Region: "Australia", City: "Brisbane", Hostname: "au-014.whiskergalaxy.com", IP: net.IP{43, 245, 160, 35}},
|
||||||
|
{Region: "Australia", City: "Canberra", Hostname: "au-010.whiskergalaxy.com", IP: net.IP{116, 206, 229, 131}},
|
||||||
|
{Region: "Australia", City: "Melbourne ", Hostname: "au-005.whiskergalaxy.com", IP: net.IP{45, 121, 209, 160}},
|
||||||
|
{Region: "Australia", City: "Melbourne ", Hostname: "au-013.whiskergalaxy.com", IP: net.IP{116, 206, 228, 67}},
|
||||||
|
{Region: "Australia", City: "Perth", Hostname: "au-004.whiskergalaxy.com", IP: net.IP{45, 121, 208, 160}},
|
||||||
|
{Region: "Australia", City: "Perth", Hostname: "au-012.whiskergalaxy.com", IP: net.IP{103, 77, 234, 211}},
|
||||||
|
{Region: "Australia", City: "Sydney", Hostname: "au-009.whiskergalaxy.com", IP: net.IP{103, 77, 233, 67}},
|
||||||
|
{Region: "Australia", City: "Sydney", Hostname: "au-015.whiskergalaxy.com", IP: net.IP{103, 1, 213, 211}},
|
||||||
|
{Region: "Australia", City: "Sydney", Hostname: "au-016.whiskergalaxy.com", IP: net.IP{103, 1, 212, 243}},
|
||||||
|
{Region: "Austria", City: "Vienna", Hostname: "at-001.whiskergalaxy.com", IP: net.IP{217, 64, 127, 11}},
|
||||||
|
{Region: "Austria", City: "Vienna", Hostname: "at-002.whiskergalaxy.com", IP: net.IP{89, 187, 168, 66}},
|
||||||
|
{Region: "Azerbaijan", City: "Baku City", Hostname: "az-001.whiskergalaxy.com", IP: net.IP{85, 132, 61, 123}},
|
||||||
|
{Region: "Belgium", City: "Brussels", Hostname: "be-001.whiskergalaxy.com", IP: net.IP{194, 187, 251, 147}},
|
||||||
|
{Region: "Belgium", City: "Brussels", Hostname: "be-002.whiskergalaxy.com", IP: net.IP{185, 232, 21, 131}},
|
||||||
|
{Region: "Bosnia", City: "Sarajevo", Hostname: "ba-001.whiskergalaxy.com", IP: net.IP{185, 99, 3, 24}},
|
||||||
|
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-004.whiskergalaxy.com", IP: net.IP{177, 67, 80, 59}},
|
||||||
|
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-005.whiskergalaxy.com", IP: net.IP{177, 54, 157, 178}},
|
||||||
|
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-006.whiskergalaxy.com", IP: net.IP{177, 54, 148, 247}},
|
||||||
|
{Region: "Bulgaria", City: "Sofia", Hostname: "bg-001.whiskergalaxy.com", IP: net.IP{185, 94, 192, 35}},
|
||||||
|
{Region: "Canada East", City: "Halifax", Hostname: "ca-029.whiskergalaxy.com", IP: net.IP{199, 204, 208, 158}},
|
||||||
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-004.whiskergalaxy.com", IP: net.IP{66, 70, 148, 80}},
|
||||||
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-027.whiskergalaxy.com", IP: net.IP{144, 168, 163, 160}},
|
||||||
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-028.whiskergalaxy.com", IP: net.IP{144, 168, 163, 193}},
|
||||||
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-032.whiskergalaxy.com", IP: net.IP{104, 227, 235, 129}},
|
||||||
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-033.whiskergalaxy.com", IP: net.IP{198, 8, 85, 195}},
|
||||||
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-034.whiskergalaxy.com", IP: net.IP{198, 8, 85, 210}},
|
||||||
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-002.whiskergalaxy.com", IP: net.IP{104, 254, 92, 11}},
|
||||||
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-009.whiskergalaxy.com", IP: net.IP{104, 254, 92, 91}},
|
||||||
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-017.whiskergalaxy.com", IP: net.IP{184, 75, 212, 91}},
|
||||||
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-025.whiskergalaxy.com", IP: net.IP{192, 190, 19, 65}},
|
||||||
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-026.whiskergalaxy.com", IP: net.IP{192, 190, 19, 97}},
|
||||||
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-030.whiskergalaxy.com", IP: net.IP{23, 154, 160, 177}},
|
||||||
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-005.whiskergalaxy.com", IP: net.IP{162, 221, 207, 95}},
|
||||||
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-011.whiskergalaxy.com", IP: net.IP{104, 218, 61, 1}},
|
||||||
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-012.whiskergalaxy.com", IP: net.IP{104, 218, 61, 33}},
|
||||||
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-016.whiskergalaxy.com", IP: net.IP{208, 78, 41, 1}},
|
||||||
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-017.whiskergalaxy.com", IP: net.IP{208, 78, 41, 131}},
|
||||||
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-019.whiskergalaxy.com", IP: net.IP{208, 78, 41, 163}},
|
||||||
|
{Region: "Chile", City: "Santiago", Hostname: "cl-001.whiskergalaxy.com", IP: net.IP{66, 203, 113, 131}},
|
||||||
|
{Region: "Chile", City: "Santiago", Hostname: "cl-002.whiskergalaxy.com", IP: net.IP{66, 203, 113, 136}},
|
||||||
|
{Region: "Colombia", City: "Bogota", Hostname: "co-001.whiskergalaxy.com", IP: net.IP{138, 121, 203, 203}},
|
||||||
|
{Region: "Colombia", City: "Bogota", Hostname: "co-002.whiskergalaxy.com", IP: net.IP{138, 186, 141, 155}},
|
||||||
|
{Region: "Croatia", City: "Zagreb", Hostname: "hr-002.whiskergalaxy.com", IP: net.IP{85, 10, 56, 129}},
|
||||||
|
{Region: "Cyprus", City: "Nicosia", Hostname: "cy-001.whiskergalaxy.com", IP: net.IP{157, 97, 132, 43}},
|
||||||
|
{Region: "Czech Republic", City: "Prague ", Hostname: "cz-002.whiskergalaxy.com", IP: net.IP{185, 246, 210, 2}},
|
||||||
|
{Region: "Czech Republic", City: "Prague", Hostname: "cz-001.whiskergalaxy.com", IP: net.IP{185, 156, 174, 11}},
|
||||||
|
{Region: "Denmark", City: "Copenhagen", Hostname: "dk-001.whiskergalaxy.com", IP: net.IP{185, 206, 224, 195}},
|
||||||
|
{Region: "Denmark", City: "Copenhagen", Hostname: "dk-002.whiskergalaxy.com", IP: net.IP{134, 90, 149, 147}},
|
||||||
|
{Region: "Estonia", City: "Tallinn", Hostname: "ee-001.whiskergalaxy.com", IP: net.IP{46, 22, 211, 251}},
|
||||||
|
{Region: "Estonia", City: "Tallinn", Hostname: "ee-002.whiskergalaxy.com", IP: net.IP{196, 196, 216, 131}},
|
||||||
|
{Region: "Fake Antarctica", City: "Troll", Hostname: "aq-001.whiskergalaxy.com", IP: net.IP{23, 154, 160, 212}},
|
||||||
|
{Region: "Fake Antarctica", City: "Troll", Hostname: "aq-002.whiskergalaxy.com", IP: net.IP{23, 154, 160, 222}},
|
||||||
|
{Region: "Finland", City: "Helsinki", Hostname: "fi-002.whiskergalaxy.com", IP: net.IP{185, 112, 82, 227}},
|
||||||
|
{Region: "Finland", City: "Helsinki", Hostname: "fi-003.whiskergalaxy.com", IP: net.IP{194, 34, 133, 82}},
|
||||||
|
{Region: "Finland", City: "Helsinki", Hostname: "fi-004.whiskergalaxy.com", IP: net.IP{196, 244, 192, 51}},
|
||||||
|
{Region: "France", City: "Paris", Hostname: "fr-004.whiskergalaxy.com", IP: net.IP{185, 156, 173, 187}},
|
||||||
|
{Region: "France", City: "Paris", Hostname: "fr-005.whiskergalaxy.com", IP: net.IP{82, 102, 18, 35}},
|
||||||
|
{Region: "France", City: "Paris", Hostname: "fr-008.whiskergalaxy.com", IP: net.IP{84, 17, 42, 34}},
|
||||||
|
{Region: "France", City: "Paris", Hostname: "fr-009.whiskergalaxy.com", IP: net.IP{84, 17, 42, 2}},
|
||||||
|
{Region: "France", City: "Paris", Hostname: "fr-011.whiskergalaxy.com", IP: net.IP{45, 89, 174, 35}},
|
||||||
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-003.whiskergalaxy.com", IP: net.IP{89, 249, 65, 19}},
|
||||||
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-006.whiskergalaxy.com", IP: net.IP{185, 130, 184, 195}},
|
||||||
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-009.whiskergalaxy.com", IP: net.IP{195, 181, 170, 66}},
|
||||||
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-010.whiskergalaxy.com", IP: net.IP{195, 181, 175, 98}},
|
||||||
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-011.whiskergalaxy.com", IP: net.IP{217, 138, 194, 115}},
|
||||||
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-012.whiskergalaxy.com", IP: net.IP{45, 87, 212, 51}},
|
||||||
|
{Region: "Greece", City: "Athens", Hostname: "gr-002.whiskergalaxy.com", IP: net.IP{78, 108, 38, 155}},
|
||||||
|
{Region: "Greece", City: "Athens", Hostname: "gr-004.whiskergalaxy.com", IP: net.IP{185, 226, 64, 111}},
|
||||||
|
{Region: "Greece", City: "Athens", Hostname: "gr-005.whiskergalaxy.com", IP: net.IP{188, 123, 126, 146}},
|
||||||
|
{Region: "Hong Kong", City: "Hong Kong", Hostname: "hk-005.whiskergalaxy.com", IP: net.IP{103, 10, 197, 99}},
|
||||||
|
{Region: "Hong Kong", City: "Hong Kong", Hostname: "hk-006.whiskergalaxy.com", IP: net.IP{84, 17, 57, 114}},
|
||||||
|
{Region: "Hungary", City: "Budapest", Hostname: "hu-001.whiskergalaxy.com", IP: net.IP{185, 104, 187, 43}},
|
||||||
|
{Region: "Iceland", City: "Reykjavik", Hostname: "is-001.whiskergalaxy.com", IP: net.IP{82, 221, 139, 38}},
|
||||||
|
{Region: "Iceland", City: "Reykjavik", Hostname: "is-002.whiskergalaxy.com", IP: net.IP{185, 165, 170, 2}},
|
||||||
|
{Region: "India", City: "Chennai", Hostname: "in-005.whiskergalaxy.com", IP: net.IP{169, 38, 68, 188}},
|
||||||
|
{Region: "India", City: "Chennai", Hostname: "in-006.whiskergalaxy.com", IP: net.IP{169, 38, 72, 14}},
|
||||||
|
{Region: "India", City: "Chennai", Hostname: "in-007.whiskergalaxy.com", IP: net.IP{169, 38, 72, 12}},
|
||||||
|
{Region: "India", City: "Mumbai", Hostname: "in-009.whiskergalaxy.com", IP: net.IP{165, 231, 253, 211}},
|
||||||
|
{Region: "India", City: "Pune", Hostname: "in-008.whiskergalaxy.com", IP: net.IP{103, 205, 140, 227}},
|
||||||
|
{Region: "Indonesia", City: "Jakarta", Hostname: "id-002.whiskergalaxy.com", IP: net.IP{45, 127, 134, 91}},
|
||||||
|
{Region: "Ireland", City: "Dublin", Hostname: "ie-001.whiskergalaxy.com", IP: net.IP{185, 24, 232, 146}},
|
||||||
|
{Region: "Ireland", City: "Dublin", Hostname: "ie-002.whiskergalaxy.com", IP: net.IP{185, 104, 219, 2}},
|
||||||
|
{Region: "Ireland", City: "Dublin", Hostname: "ie-003.whiskergalaxy.com", IP: net.IP{23, 92, 127, 35}},
|
||||||
|
{Region: "Israel", City: "Ashdod", Hostname: "il-002.whiskergalaxy.com", IP: net.IP{185, 191, 205, 139}},
|
||||||
|
{Region: "Israel", City: "Jerusalem", Hostname: "il-001.whiskergalaxy.com", IP: net.IP{160, 116, 0, 27}},
|
||||||
|
{Region: "Italy", City: "Milan", Hostname: "it-001.whiskergalaxy.com", IP: net.IP{37, 120, 135, 83}},
|
||||||
|
{Region: "Italy", City: "Milan", Hostname: "it-004.whiskergalaxy.com", IP: net.IP{84, 17, 59, 66}},
|
||||||
|
{Region: "Italy", City: "Milan", Hostname: "it-005.whiskergalaxy.com", IP: net.IP{89, 40, 182, 3}},
|
||||||
|
{Region: "Italy", City: "Rome", Hostname: "it-003.whiskergalaxy.com", IP: net.IP{87, 101, 94, 195}},
|
||||||
|
{Region: "Italy", City: "Rome", Hostname: "it-006.whiskergalaxy.com", IP: net.IP{37, 120, 207, 19}},
|
||||||
|
{Region: "Japan", City: "Tokyo", Hostname: "jp-004.whiskergalaxy.com", IP: net.IP{193, 148, 16, 243}},
|
||||||
|
{Region: "Japan", City: "Tokyo", Hostname: "jp-006.whiskergalaxy.com", IP: net.IP{138, 199, 22, 162}},
|
||||||
|
{Region: "Latvia", City: "Riga", Hostname: "lv-003.whiskergalaxy.com", IP: net.IP{85, 254, 72, 23}},
|
||||||
|
{Region: "Latvia", City: "Riga", Hostname: "lv-004.whiskergalaxy.com", IP: net.IP{89, 111, 33, 220}},
|
||||||
|
{Region: "Lithuania", City: "Siauliai", Hostname: "lt-003.whiskergalaxy.com", IP: net.IP{85, 206, 163, 225}},
|
||||||
|
{Region: "Malaysia", City: "Kuala Lumpur", Hostname: "my-001.whiskergalaxy.com", IP: net.IP{103, 106, 250, 31}},
|
||||||
|
{Region: "Malaysia", City: "Kuala Lumpur", Hostname: "my-003.whiskergalaxy.com", IP: net.IP{103, 212, 69, 232}},
|
||||||
|
{Region: "Mexico", City: "Guadalajara", Hostname: "mx-007.whiskergalaxy.com", IP: net.IP{201, 131, 125, 107}},
|
||||||
|
{Region: "Mexico", City: "Guadalajara", Hostname: "mx-008.whiskergalaxy.com", IP: net.IP{143, 255, 57, 67}},
|
||||||
|
{Region: "Mexico", City: "Mexico City", Hostname: "mx-009.whiskergalaxy.com", IP: net.IP{190, 103, 179, 211}},
|
||||||
|
{Region: "Mexico", City: "Mexico City", Hostname: "mx-010.whiskergalaxy.com", IP: net.IP{190, 103, 179, 217}},
|
||||||
|
{Region: "Moldova", City: "Chisinau", Hostname: "md-002.whiskergalaxy.com", IP: net.IP{178, 175, 144, 123}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-001.whiskergalaxy.com", IP: net.IP{46, 166, 143, 98}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-005.whiskergalaxy.com", IP: net.IP{185, 212, 171, 131}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-008.whiskergalaxy.com", IP: net.IP{185, 253, 96, 3}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-011.whiskergalaxy.com", IP: net.IP{84, 17, 46, 2}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-012.whiskergalaxy.com", IP: net.IP{37, 120, 192, 19}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-013.whiskergalaxy.com", IP: net.IP{72, 11, 157, 67}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-014.whiskergalaxy.com", IP: net.IP{72, 11, 157, 35}},
|
||||||
|
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-015.whiskergalaxy.com", IP: net.IP{109, 201, 130, 2}},
|
||||||
|
{Region: "New Zealand", City: "Auckland ", Hostname: "nz-003.whiskergalaxy.com", IP: net.IP{103, 108, 94, 163}},
|
||||||
|
{Region: "New Zealand", City: "Auckland", Hostname: "nz-002.whiskergalaxy.com", IP: net.IP{103, 62, 49, 113}},
|
||||||
|
{Region: "North Macedonia", City: "Skopje", Hostname: "mk-001.whiskergalaxy.com", IP: net.IP{185, 225, 28, 51}},
|
||||||
|
{Region: "Norway", City: "Oslo", Hostname: "no-003.whiskergalaxy.com", IP: net.IP{185, 206, 225, 131}},
|
||||||
|
{Region: "Norway", City: "Oslo", Hostname: "no-006.whiskergalaxy.com", IP: net.IP{37, 120, 203, 67}},
|
||||||
|
{Region: "Panama", City: "Panama City", Hostname: "pa-001.whiskergalaxy.com", IP: net.IP{138, 186, 142, 203}},
|
||||||
|
{Region: "Peru", City: "Lima", Hostname: "pe-002.whiskergalaxy.com", IP: net.IP{190, 120, 229, 139}},
|
||||||
|
{Region: "Philippines", City: "Manila", Hostname: "ph-003.whiskergalaxy.com", IP: net.IP{141, 98, 215, 211}},
|
||||||
|
{Region: "Philippines", City: "San Antonio", Hostname: "ph-002.whiskergalaxy.com", IP: net.IP{103, 103, 0, 118}},
|
||||||
|
{Region: "Poland", City: "Warsaw", Hostname: "pl-002.whiskergalaxy.com", IP: net.IP{185, 244, 214, 35}},
|
||||||
|
{Region: "Poland", City: "Warsaw", Hostname: "pl-004.whiskergalaxy.com", IP: net.IP{84, 17, 55, 98}},
|
||||||
|
{Region: "Poland", City: "Warsaw", Hostname: "pl-005.whiskergalaxy.com", IP: net.IP{5, 133, 11, 116}},
|
||||||
|
{Region: "Portugal", City: "Lisbon", Hostname: "pt-002.whiskergalaxy.com", IP: net.IP{94, 46, 13, 215}},
|
||||||
|
{Region: "Portugal", City: "Lisbon", Hostname: "pt-003.whiskergalaxy.com", IP: net.IP{185, 15, 21, 66}},
|
||||||
|
{Region: "Romania", City: "Bucharest", Hostname: "ro-006.whiskergalaxy.com", IP: net.IP{89, 46, 103, 147}},
|
||||||
|
{Region: "Romania", City: "Bucharest", Hostname: "ro-008.whiskergalaxy.com", IP: net.IP{91, 207, 102, 147}},
|
||||||
|
{Region: "Russia", City: "Moscow", Hostname: "ru-010.whiskergalaxy.com", IP: net.IP{95, 213, 193, 227}},
|
||||||
|
{Region: "Russia", City: "Moscow", Hostname: "ru-011.whiskergalaxy.com", IP: net.IP{95, 213, 193, 195}},
|
||||||
|
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-005.whiskergalaxy.com", IP: net.IP{185, 22, 175, 132}},
|
||||||
|
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-008.whiskergalaxy.com", IP: net.IP{94, 242, 62, 19}},
|
||||||
|
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-009.whiskergalaxy.com", IP: net.IP{94, 242, 62, 67}},
|
||||||
|
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-012.whiskergalaxy.com", IP: net.IP{188, 124, 42, 115}},
|
||||||
|
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-013.whiskergalaxy.com", IP: net.IP{188, 124, 42, 99}},
|
||||||
|
{Region: "Serbia", City: "Belgrade", Hostname: "rs-003.whiskergalaxy.com", IP: net.IP{141, 98, 103, 19}},
|
||||||
|
{Region: "Singapore", City: "Singapore", Hostname: "sg-003.whiskergalaxy.com", IP: net.IP{185, 200, 117, 163}},
|
||||||
|
{Region: "Singapore", City: "Singapore", Hostname: "sg-004.whiskergalaxy.com", IP: net.IP{82, 102, 25, 131}},
|
||||||
|
{Region: "Singapore", City: "Singapore", Hostname: "sg-005.whiskergalaxy.com", IP: net.IP{103, 62, 48, 224}},
|
||||||
|
{Region: "Singapore", City: "Singapore", Hostname: "sg-006.whiskergalaxy.com", IP: net.IP{156, 146, 56, 98}},
|
||||||
|
{Region: "Singapore", City: "Singapore", Hostname: "sg-007.whiskergalaxy.com", IP: net.IP{156, 146, 56, 111}},
|
||||||
|
{Region: "Slovakia", City: "Bratislava", Hostname: "sk-001.whiskergalaxy.com", IP: net.IP{185, 245, 85, 3}},
|
||||||
|
{Region: "South Africa", City: "Johannesburg", Hostname: "za-002.whiskergalaxy.com", IP: net.IP{129, 232, 167, 211}},
|
||||||
|
{Region: "South Africa", City: "Johannesburg", Hostname: "za-003.whiskergalaxy.com", IP: net.IP{197, 242, 156, 53}},
|
||||||
|
{Region: "South Africa", City: "Johannesburg", Hostname: "za-004.whiskergalaxy.com", IP: net.IP{165, 73, 248, 91}},
|
||||||
|
{Region: "South Korea", City: "Seoul", Hostname: "kr-001.whiskergalaxy.com", IP: net.IP{103, 212, 223, 3}},
|
||||||
|
{Region: "South Korea", City: "Seoul", Hostname: "kr-002.whiskergalaxy.com", IP: net.IP{218, 232, 76, 179}},
|
||||||
|
{Region: "South Korea", City: "Seoul", Hostname: "kr-005.whiskergalaxy.com", IP: net.IP{45, 133, 194, 235}},
|
||||||
|
{Region: "Spain", City: "Barcelona", Hostname: "es-001.whiskergalaxy.com", IP: net.IP{185, 253, 99, 131}},
|
||||||
|
{Region: "Spain", City: "Barcelona", Hostname: "es-004.whiskergalaxy.com", IP: net.IP{37, 120, 142, 227}},
|
||||||
|
{Region: "Spain", City: "Madrid", Hostname: "es-002.whiskergalaxy.com", IP: net.IP{89, 238, 178, 43}},
|
||||||
|
{Region: "Spain", City: "Madrid", Hostname: "es-003.whiskergalaxy.com", IP: net.IP{217, 138, 218, 99}},
|
||||||
|
{Region: "Sweden", City: "Stockholm", Hostname: "se-001.whiskergalaxy.com", IP: net.IP{31, 13, 191, 67}},
|
||||||
|
{Region: "Sweden", City: "Stockholm", Hostname: "se-002.whiskergalaxy.com", IP: net.IP{79, 142, 76, 198}},
|
||||||
|
{Region: "Sweden", City: "Stockholm", Hostname: "se-003.whiskergalaxy.com", IP: net.IP{195, 181, 166, 129}},
|
||||||
|
{Region: "Switzerland", City: "Zurich", Hostname: "ch-001.whiskergalaxy.com", IP: net.IP{31, 7, 57, 242}},
|
||||||
|
{Region: "Switzerland", City: "Zurich", Hostname: "ch-003.whiskergalaxy.com", IP: net.IP{185, 156, 175, 179}},
|
||||||
|
{Region: "Switzerland", City: "Zurich", Hostname: "ch-005.whiskergalaxy.com", IP: net.IP{89, 187, 165, 98}},
|
||||||
|
{Region: "Switzerland", City: "Zurich", Hostname: "ch-006.whiskergalaxy.com", IP: net.IP{84, 17, 53, 2}},
|
||||||
|
{Region: "Switzerland", City: "Zurich", Hostname: "ch-008.whiskergalaxy.com", IP: net.IP{37, 120, 213, 163}},
|
||||||
|
{Region: "Taiwan", City: "Taipei", Hostname: "tw-008.whiskergalaxy.com", IP: net.IP{103, 4, 29, 77}},
|
||||||
|
{Region: "Taiwan", City: "Taipei", Hostname: "tw-009.whiskergalaxy.com", IP: net.IP{185, 189, 160, 12}},
|
||||||
|
{Region: "Taiwan", City: "Taipei", Hostname: "tw-010.whiskergalaxy.com", IP: net.IP{185, 189, 160, 27}},
|
||||||
|
{Region: "Taiwan", City: "Taipei", Hostname: "tw-011.whiskergalaxy.com", IP: net.IP{185, 189, 160, 32}},
|
||||||
|
{Region: "Thailand", City: "Bangkok", Hostname: "th-003.whiskergalaxy.com", IP: net.IP{27, 254, 130, 221}},
|
||||||
|
{Region: "Thailand", City: "Bangkok", Hostname: "th-005.whiskergalaxy.com", IP: net.IP{202, 129, 16, 147}},
|
||||||
|
{Region: "Thailand", City: "Bangkok", Hostname: "th-006.whiskergalaxy.com", IP: net.IP{202, 129, 16, 155}},
|
||||||
|
{Region: "Tunisia", City: "Tunis", Hostname: "tn-001.whiskergalaxy.com", IP: net.IP{41, 231, 5, 23}},
|
||||||
|
{Region: "Turkey", City: "Bursa", Hostname: "tr-001.whiskergalaxy.com", IP: net.IP{45, 123, 118, 156}},
|
||||||
|
{Region: "Turkey", City: "Istanbul", Hostname: "tr-004.whiskergalaxy.com", IP: net.IP{45, 123, 119, 11}},
|
||||||
|
{Region: "Turkey", City: "Istanbul", Hostname: "tr-006.whiskergalaxy.com", IP: net.IP{185, 125, 33, 227}},
|
||||||
|
{Region: "Turkey", City: "Istanbul", Hostname: "tr-009.whiskergalaxy.com", IP: net.IP{79, 98, 131, 43}},
|
||||||
|
{Region: "Turkey", City: "Istanbul", Hostname: "tr-011.whiskergalaxy.com", IP: net.IP{176, 53, 113, 163}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-015.whiskergalaxy.com", IP: net.IP{107, 150, 31, 131}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-016.whiskergalaxy.com", IP: net.IP{104, 129, 18, 3}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-020.whiskergalaxy.com", IP: net.IP{104, 129, 18, 131}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-034.whiskergalaxy.com", IP: net.IP{161, 129, 70, 195}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-046.whiskergalaxy.com", IP: net.IP{198, 12, 76, 211}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-049.whiskergalaxy.com", IP: net.IP{107, 150, 31, 3}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-050.whiskergalaxy.com", IP: net.IP{107, 150, 31, 67}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-051.whiskergalaxy.com", IP: net.IP{162, 222, 198, 67}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-054.whiskergalaxy.com", IP: net.IP{104, 223, 92, 163}},
|
||||||
|
{Region: "US Central", City: "Atlanta", Hostname: "us-central-056.whiskergalaxy.com", IP: net.IP{206, 217, 143, 131}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-014.whiskergalaxy.com", IP: net.IP{69, 12, 94, 67}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-029.whiskergalaxy.com", IP: net.IP{198, 55, 125, 195}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-036.whiskergalaxy.com", IP: net.IP{204, 44, 112, 67}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-037.whiskergalaxy.com", IP: net.IP{204, 44, 112, 131}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-044.whiskergalaxy.com", IP: net.IP{206, 217, 139, 195}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-045.whiskergalaxy.com", IP: net.IP{172, 241, 131, 129}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-055.whiskergalaxy.com", IP: net.IP{206, 217, 139, 19}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-057.whiskergalaxy.com", IP: net.IP{172, 241, 26, 78}},
|
||||||
|
{Region: "US Central", City: "Dallas", Hostname: "us-central-060.whiskergalaxy.com", IP: net.IP{198, 55, 126, 131}},
|
||||||
|
{Region: "US Central", City: "Denver", Hostname: "us-central-043.whiskergalaxy.com", IP: net.IP{199, 115, 96, 83}},
|
||||||
|
{Region: "US Central", City: "Denver", Hostname: "us-central-058.whiskergalaxy.com", IP: net.IP{198, 54, 128, 116}},
|
||||||
|
{Region: "US Central", City: "Denver", Hostname: "us-central-062.whiskergalaxy.com", IP: net.IP{174, 128, 251, 147}},
|
||||||
|
{Region: "US Central", City: "Kansas City", Hostname: "us-central-063.whiskergalaxy.com", IP: net.IP{38, 146, 5, 51}},
|
||||||
|
{Region: "US East", City: "Boston", Hostname: "us-east-039.whiskergalaxy.com", IP: net.IP{199, 217, 104, 227}},
|
||||||
|
{Region: "US East", City: "Boston", Hostname: "us-east-051.whiskergalaxy.com", IP: net.IP{199, 217, 105, 227}},
|
||||||
|
{Region: "US East", City: "Buffalo", Hostname: "us-east-045.whiskergalaxy.com", IP: net.IP{104, 168, 34, 147}},
|
||||||
|
{Region: "US East", City: "Buffalo", Hostname: "us-east-065.whiskergalaxy.com", IP: net.IP{198, 12, 64, 35}},
|
||||||
|
{Region: "US East", City: "Charlotte", Hostname: "us-east-040.whiskergalaxy.com", IP: net.IP{67, 21, 32, 145}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-015.whiskergalaxy.com", IP: net.IP{68, 235, 50, 227}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-019.whiskergalaxy.com", IP: net.IP{23, 226, 141, 195}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-022.whiskergalaxy.com", IP: net.IP{167, 160, 172, 3}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-047.whiskergalaxy.com", IP: net.IP{23, 83, 91, 170}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-053.whiskergalaxy.com", IP: net.IP{107, 150, 29, 131}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-069.whiskergalaxy.com", IP: net.IP{68, 235, 35, 172}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-071.whiskergalaxy.com", IP: net.IP{68, 235, 35, 12}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-077.whiskergalaxy.com", IP: net.IP{68, 235, 43, 204}},
|
||||||
|
{Region: "US East", City: "Chicago", Hostname: "us-east-083.whiskergalaxy.com", IP: net.IP{23, 19, 122, 225}},
|
||||||
|
{Region: "US East", City: "Cleveland", Hostname: "us-east-078.whiskergalaxy.com", IP: net.IP{38, 101, 74, 19}},
|
||||||
|
{Region: "US East", City: "Detroit", Hostname: "us-east-079.whiskergalaxy.com", IP: net.IP{104, 244, 210, 51}},
|
||||||
|
{Region: "US East", City: "Miami", Hostname: "us-east-006.whiskergalaxy.com", IP: net.IP{173, 44, 36, 67}},
|
||||||
|
{Region: "US East", City: "Miami", Hostname: "us-east-012.whiskergalaxy.com", IP: net.IP{45, 87, 214, 35}},
|
||||||
|
{Region: "US East", City: "Miami", Hostname: "us-east-028.whiskergalaxy.com", IP: net.IP{104, 223, 127, 195}},
|
||||||
|
{Region: "US East", City: "Miami", Hostname: "us-east-049.whiskergalaxy.com", IP: net.IP{23, 82, 136, 93}},
|
||||||
|
{Region: "US East", City: "Miami", Hostname: "us-east-067.whiskergalaxy.com", IP: net.IP{86, 106, 87, 83}},
|
||||||
|
{Region: "US East", City: "Miami", Hostname: "us-east-084.whiskergalaxy.com", IP: net.IP{23, 82, 137, 72}},
|
||||||
|
{Region: "US East", City: "New Jersey", Hostname: "us-east-020.whiskergalaxy.com", IP: net.IP{162, 222, 195, 67}},
|
||||||
|
{Region: "US East", City: "New Jersey", Hostname: "us-east-054.whiskergalaxy.com", IP: net.IP{167, 160, 167, 195}},
|
||||||
|
{Region: "US East", City: "New York", Hostname: "us-east-013.whiskergalaxy.com", IP: net.IP{185, 232, 22, 195}},
|
||||||
|
{Region: "US East", City: "New York", Hostname: "us-east-046.whiskergalaxy.com", IP: net.IP{206, 217, 129, 227}},
|
||||||
|
{Region: "US East", City: "New York", Hostname: "us-east-050.whiskergalaxy.com", IP: net.IP{173, 208, 45, 33}},
|
||||||
|
{Region: "US East", City: "New York", Hostname: "us-east-064.whiskergalaxy.com", IP: net.IP{206, 217, 128, 3}},
|
||||||
|
{Region: "US East", City: "New York", Hostname: "us-east-068.whiskergalaxy.com", IP: net.IP{142, 234, 200, 176}},
|
||||||
|
{Region: "US East", City: "Orlando", Hostname: "us-east-052.whiskergalaxy.com", IP: net.IP{198, 147, 22, 225}},
|
||||||
|
{Region: "US East", City: "Orlando", Hostname: "us-east-082.whiskergalaxy.com", IP: net.IP{66, 115, 182, 131}},
|
||||||
|
{Region: "US East", City: "Philadelphia", Hostname: "us-east-060.whiskergalaxy.com", IP: net.IP{76, 72, 175, 99}},
|
||||||
|
{Region: "US East", City: "Philadelphia", Hostname: "us-east-061.whiskergalaxy.com", IP: net.IP{156, 96, 59, 102}},
|
||||||
|
{Region: "US East", City: "Tampa", Hostname: "us-east-080.whiskergalaxy.com", IP: net.IP{209, 216, 79, 83}},
|
||||||
|
{Region: "US East", City: "Tampa", Hostname: "us-east-081.whiskergalaxy.com", IP: net.IP{209, 216, 79, 67}},
|
||||||
|
{Region: "US East", City: "Washington DC", Hostname: "us-east-048.whiskergalaxy.com", IP: net.IP{23, 82, 8, 143}},
|
||||||
|
{Region: "US East", City: "Washington DC", Hostname: "us-east-055.whiskergalaxy.com", IP: net.IP{23, 105, 170, 139}},
|
||||||
|
{Region: "US East", City: "Washington DC", Hostname: "us-east-057.whiskergalaxy.com", IP: net.IP{23, 105, 170, 130}},
|
||||||
|
{Region: "US East", City: "Washington DC", Hostname: "us-east-058.whiskergalaxy.com", IP: net.IP{23, 105, 170, 151}},
|
||||||
|
{Region: "US West", City: "Bend", Hostname: "us-west-038.whiskergalaxy.com", IP: net.IP{104, 152, 222, 33}},
|
||||||
|
{Region: "US West", City: "Las Vegas", Hostname: "us-west-018.whiskergalaxy.com", IP: net.IP{82, 102, 30, 67}},
|
||||||
|
{Region: "US West", City: "Las Vegas", Hostname: "us-west-030.whiskergalaxy.com", IP: net.IP{37, 120, 147, 163}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-004.whiskergalaxy.com", IP: net.IP{185, 236, 200, 35}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-015.whiskergalaxy.com", IP: net.IP{216, 45, 53, 131}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-027.whiskergalaxy.com", IP: net.IP{212, 103, 49, 67}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-040.whiskergalaxy.com", IP: net.IP{89, 187, 185, 34}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-044.whiskergalaxy.com", IP: net.IP{192, 3, 20, 51}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-047.whiskergalaxy.com", IP: net.IP{172, 241, 214, 202}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-055.whiskergalaxy.com", IP: net.IP{104, 129, 3, 67}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-059.whiskergalaxy.com", IP: net.IP{104, 129, 3, 163}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-060.whiskergalaxy.com", IP: net.IP{217, 138, 217, 51}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-063.whiskergalaxy.com", IP: net.IP{198, 23, 242, 147}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-065.whiskergalaxy.com", IP: net.IP{217, 138, 217, 211}},
|
||||||
|
{Region: "US West", City: "Los Angeles", Hostname: "us-west-066.whiskergalaxy.com", IP: net.IP{89, 187, 187, 98}},
|
||||||
|
{Region: "US West", City: "Phoenix", Hostname: "us-west-046.whiskergalaxy.com", IP: net.IP{23, 83, 130, 166}},
|
||||||
|
{Region: "US West", City: "Phoenix", Hostname: "us-west-061.whiskergalaxy.com", IP: net.IP{23, 83, 131, 187}},
|
||||||
|
{Region: "US West", City: "San Francisco", Hostname: "us-west-048.whiskergalaxy.com", IP: net.IP{172, 241, 250, 131}},
|
||||||
|
{Region: "US West", City: "San Francisco", Hostname: "us-west-053.whiskergalaxy.com", IP: net.IP{209, 58, 129, 121}},
|
||||||
|
{Region: "US West", City: "San Francisco", Hostname: "us-west-054.whiskergalaxy.com", IP: net.IP{172, 255, 125, 141}},
|
||||||
|
{Region: "US West", City: "San Jose", Hostname: "us-west-052.whiskergalaxy.com", IP: net.IP{66, 115, 176, 3}},
|
||||||
|
{Region: "US West", City: "San Jose", Hostname: "us-west-067.whiskergalaxy.com", IP: net.IP{66, 115, 165, 227}},
|
||||||
|
{Region: "US West", City: "Santa Clara", Hostname: "us-west-050.whiskergalaxy.com", IP: net.IP{167, 88, 60, 227}},
|
||||||
|
{Region: "US West", City: "Santa Clara", Hostname: "us-west-051.whiskergalaxy.com", IP: net.IP{167, 88, 60, 243}},
|
||||||
|
{Region: "US West", City: "Seattle", Hostname: "us-west-043.whiskergalaxy.com", IP: net.IP{23, 94, 74, 99}},
|
||||||
|
{Region: "US West", City: "Seattle", Hostname: "us-west-045.whiskergalaxy.com", IP: net.IP{64, 120, 2, 174}},
|
||||||
|
{Region: "US West", City: "Seattle", Hostname: "us-west-056.whiskergalaxy.com", IP: net.IP{104, 129, 56, 67}},
|
||||||
|
{Region: "US West", City: "Seattle", Hostname: "us-west-057.whiskergalaxy.com", IP: net.IP{104, 129, 56, 131}},
|
||||||
|
{Region: "US West", City: "Seattle", Hostname: "us-west-062.whiskergalaxy.com", IP: net.IP{198, 12, 116, 195}},
|
||||||
|
{Region: "Ukraine", City: "Kyiv", Hostname: "ua-006.whiskergalaxy.com", IP: net.IP{45, 141, 156, 11}},
|
||||||
|
{Region: "Ukraine", City: "Kyiv", Hostname: "ua-007.whiskergalaxy.com", IP: net.IP{45, 141, 156, 50}},
|
||||||
|
{Region: "United Arab Emirates", City: "Dubai", Hostname: "ae-001.whiskergalaxy.com", IP: net.IP{45, 9, 249, 43}},
|
||||||
|
{Region: "United Kingdom", City: "Edinburgh", Hostname: "uk-026.whiskergalaxy.com", IP: net.IP{193, 36, 118, 243}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-007.whiskergalaxy.com", IP: net.IP{185, 212, 168, 133}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-013.whiskergalaxy.com", IP: net.IP{89, 238, 150, 229}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-014.whiskergalaxy.com", IP: net.IP{2, 58, 29, 145}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-015.whiskergalaxy.com", IP: net.IP{2, 58, 29, 17}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-017.whiskergalaxy.com", IP: net.IP{84, 17, 50, 130}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-021.whiskergalaxy.com", IP: net.IP{212, 102, 63, 32}},
|
||||||
|
{Region: "United Kingdom", City: "London", Hostname: "uk-022.whiskergalaxy.com", IP: net.IP{212, 102, 63, 62}},
|
||||||
|
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-008.whiskergalaxy.com", IP: net.IP{81, 92, 207, 69}},
|
||||||
|
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-010.whiskergalaxy.com", IP: net.IP{89, 238, 135, 133}},
|
||||||
|
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-025.whiskergalaxy.com", IP: net.IP{89, 44, 201, 99}},
|
||||||
|
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-027.whiskergalaxy.com", IP: net.IP{84, 252, 95, 131}},
|
||||||
|
{Region: "Vietnam", City: "Hanoi", Hostname: "vn-001.whiskergalaxy.com", IP: net.IP{103, 9, 76, 197}},
|
||||||
|
{Region: "Vietnam", City: "Hanoi", Hostname: "vn-002.whiskergalaxy.com", IP: net.IP{103, 9, 79, 186}},
|
||||||
|
{Region: "Vietnam", City: "Hanoi", Hostname: "vn-003.whiskergalaxy.com", IP: net.IP{103, 9, 79, 219}},
|
||||||
|
{Region: "WINDFLIX CA", City: "Toronto", Hostname: "wf-ca-003.whiskergalaxy.com", IP: net.IP{104, 218, 60, 111}},
|
||||||
|
{Region: "WINDFLIX CA", City: "Toronto", Hostname: "wf-ca-004.whiskergalaxy.com", IP: net.IP{104, 254, 92, 99}},
|
||||||
|
{Region: "WINDFLIX JP", City: "Tokyo", Hostname: "wf-jp-002.whiskergalaxy.com", IP: net.IP{5, 181, 235, 67}},
|
||||||
|
{Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-001.whiskergalaxy.com", IP: net.IP{45, 9, 248, 3}},
|
||||||
|
{Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-006.whiskergalaxy.com", IP: net.IP{81, 92, 200, 85}},
|
||||||
|
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-010.whiskergalaxy.com", IP: net.IP{38, 132, 122, 195}},
|
||||||
|
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-011.whiskergalaxy.com", IP: net.IP{38, 132, 122, 131}},
|
||||||
|
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-012.whiskergalaxy.com", IP: net.IP{185, 232, 22, 131}},
|
||||||
|
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-013.whiskergalaxy.com", IP: net.IP{217, 138, 206, 211}},
|
||||||
|
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-014.whiskergalaxy.com", IP: net.IP{77, 81, 136, 99}},
|
||||||
|
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-015.whiskergalaxy.com", IP: net.IP{38, 132, 101, 211}},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *configurator) Start(verbosityDetailsLevel uint8) (stdout io.ReadCloser, waitFn func() error, err error) {
|
|
||||||
c.logger.Info("%s: starting unbound", logPrefix)
|
|
||||||
args := []string{"-d", "-c", string(constants.UnboundConf)}
|
|
||||||
if verbosityDetailsLevel > 0 {
|
|
||||||
args = append(args, "-"+strings.Repeat("v", int(verbosityDetailsLevel)))
|
|
||||||
}
|
|
||||||
// Only logs to stderr
|
|
||||||
_, stdout, waitFn, err = c.commander.Start("unbound", args...)
|
|
||||||
return stdout, waitFn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *configurator) Version() (version string, err error) {
|
|
||||||
output, err := c.commander.Run("unbound", "-V")
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("unbound version: %w", err)
|
|
||||||
}
|
|
||||||
for _, line := range strings.Split(output, "\n") {
|
|
||||||
if strings.Contains(line, "Version ") {
|
|
||||||
words := strings.Fields(line)
|
|
||||||
if len(words) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
version = words[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if version == "" {
|
|
||||||
return "", fmt.Errorf("unbound version was not found in %q", output)
|
|
||||||
}
|
|
||||||
return version, nil
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
commandMocks "github.com/qdm12/golibs/command/mocks"
|
|
||||||
loggingMocks "github.com/qdm12/golibs/logging/mocks"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Start(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
logger := &loggingMocks.Logger{}
|
|
||||||
logger.On("Info", "%s: starting unbound", logPrefix).Once()
|
|
||||||
commander := &commandMocks.Commander{}
|
|
||||||
commander.On("Start", "unbound", "-d", "-c", string(constants.UnboundConf), "-vv").
|
|
||||||
Return(nil, nil, nil, nil).Once()
|
|
||||||
c := &configurator{commander: commander, logger: logger}
|
|
||||||
stdout, waitFn, err := c.Start(2)
|
|
||||||
assert.Nil(t, stdout)
|
|
||||||
assert.Nil(t, waitFn)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
logger.AssertExpectations(t)
|
|
||||||
commander.AssertExpectations(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Version(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
tests := map[string]struct {
|
|
||||||
runOutput string
|
|
||||||
runErr error
|
|
||||||
version string
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
"no data": {
|
|
||||||
err: fmt.Errorf(`unbound version was not found in ""`),
|
|
||||||
},
|
|
||||||
"2 lines with version": {
|
|
||||||
runOutput: "Version \nVersion 1.0-a hello\n",
|
|
||||||
version: "1.0-a",
|
|
||||||
},
|
|
||||||
"run error": {
|
|
||||||
runErr: fmt.Errorf("error"),
|
|
||||||
err: fmt.Errorf("unbound version: error"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
commander := &commandMocks.Commander{}
|
|
||||||
commander.On("Run", "unbound", "-V").
|
|
||||||
Return(tc.runOutput, tc.runErr).Once()
|
|
||||||
c := &configurator{commander: commander}
|
|
||||||
version, err := c.Version()
|
|
||||||
if tc.err != nil {
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Equal(t, tc.err.Error(), err.Error())
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
assert.Equal(t, tc.version, version)
|
|
||||||
commander.AssertExpectations(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/qdm12/golibs/files"
|
|
||||||
"github.com/qdm12/golibs/logging"
|
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/settings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *configurator) MakeUnboundConf(settings settings.DNS, uid, gid int) (err error) {
|
|
||||||
c.logger.Info("%s: generating Unbound configuration", logPrefix)
|
|
||||||
lines, warnings, err := generateUnboundConf(settings, c.client, c.logger)
|
|
||||||
for _, warning := range warnings {
|
|
||||||
c.logger.Warn(warning)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.fileManager.WriteLinesToFile(
|
|
||||||
string(constants.UnboundConf),
|
|
||||||
lines,
|
|
||||||
files.Ownership(uid, gid),
|
|
||||||
files.Permissions(0400))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeUnboundConf generates an Unbound configuration from the user provided settings
|
|
||||||
func generateUnboundConf(settings settings.DNS, client network.Client, logger logging.Logger) (lines []string, warnings []error, err error) {
|
|
||||||
serverSection := map[string]string{
|
|
||||||
// Logging
|
|
||||||
"verbosity": fmt.Sprintf("%d", settings.VerbosityLevel),
|
|
||||||
"val-log-level": fmt.Sprintf("%d", settings.ValidationLogLevel),
|
|
||||||
"use-syslog": "no",
|
|
||||||
// Performance
|
|
||||||
"num-threads": "1",
|
|
||||||
"prefetch": "yes",
|
|
||||||
"prefetch-key": "yes",
|
|
||||||
"key-cache-size": "16m",
|
|
||||||
"key-cache-slabs": "4",
|
|
||||||
"msg-cache-size": "4m",
|
|
||||||
"msg-cache-slabs": "4",
|
|
||||||
"rrset-cache-size": "4m",
|
|
||||||
"rrset-cache-slabs": "4",
|
|
||||||
"cache-min-ttl": "3600",
|
|
||||||
"cache-max-ttl": "9000",
|
|
||||||
// Privacy
|
|
||||||
"rrset-roundrobin": "yes",
|
|
||||||
"hide-identity": "yes",
|
|
||||||
"hide-version": "yes",
|
|
||||||
// Security
|
|
||||||
"tls-cert-bundle": fmt.Sprintf("%q", constants.CACertificates),
|
|
||||||
"root-hints": fmt.Sprintf("%q", constants.RootHints),
|
|
||||||
"trust-anchor-file": fmt.Sprintf("%q", constants.RootKey),
|
|
||||||
"harden-below-nxdomain": "yes",
|
|
||||||
"harden-referral-path": "yes",
|
|
||||||
"harden-algo-downgrade": "yes",
|
|
||||||
// Network
|
|
||||||
"do-ip4": "yes",
|
|
||||||
"do-ip6": "no",
|
|
||||||
"interface": "127.0.0.1",
|
|
||||||
"port": "53",
|
|
||||||
// Other
|
|
||||||
"username": "\"nonrootuser\"",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block lists
|
|
||||||
hostnamesLines, ipsLines, warnings := buildBlocked(client,
|
|
||||||
settings.BlockMalicious, settings.BlockAds, settings.BlockSurveillance,
|
|
||||||
settings.AllowedHostnames, settings.PrivateAddresses,
|
|
||||||
)
|
|
||||||
logger.Info("%s: %d hostnames blocked overall", logPrefix, len(hostnamesLines))
|
|
||||||
logger.Info("%s: %d IP addresses blocked overall", logPrefix, len(ipsLines))
|
|
||||||
sort.Slice(hostnamesLines, func(i, j int) bool { // for unit tests really
|
|
||||||
return hostnamesLines[i] < hostnamesLines[j]
|
|
||||||
})
|
|
||||||
sort.Slice(ipsLines, func(i, j int) bool { // for unit tests really
|
|
||||||
return ipsLines[i] < ipsLines[j]
|
|
||||||
})
|
|
||||||
|
|
||||||
// Server
|
|
||||||
lines = append(lines, "server:")
|
|
||||||
var serverLines []string
|
|
||||||
for k, v := range serverSection {
|
|
||||||
serverLines = append(serverLines, " "+k+": "+v)
|
|
||||||
}
|
|
||||||
sort.Slice(serverLines, func(i, j int) bool {
|
|
||||||
return serverLines[i] < serverLines[j]
|
|
||||||
})
|
|
||||||
lines = append(lines, serverLines...)
|
|
||||||
lines = append(lines, hostnamesLines...)
|
|
||||||
lines = append(lines, ipsLines...)
|
|
||||||
|
|
||||||
// Forward zone
|
|
||||||
lines = append(lines, "forward-zone:")
|
|
||||||
forwardZoneSection := map[string]string{
|
|
||||||
"name": "\".\"",
|
|
||||||
"forward-tls-upstream": "yes",
|
|
||||||
}
|
|
||||||
if settings.Caching {
|
|
||||||
forwardZoneSection["forward-no-cache"] = "no"
|
|
||||||
} else {
|
|
||||||
forwardZoneSection["forward-no-cache"] = "yes"
|
|
||||||
}
|
|
||||||
var forwardZoneLines []string
|
|
||||||
for k, v := range forwardZoneSection {
|
|
||||||
forwardZoneLines = append(forwardZoneLines, " "+k+": "+v)
|
|
||||||
}
|
|
||||||
sort.Slice(forwardZoneLines, func(i, j int) bool {
|
|
||||||
return forwardZoneLines[i] < forwardZoneLines[j]
|
|
||||||
})
|
|
||||||
for _, provider := range settings.Providers {
|
|
||||||
providerData, ok := constants.DNSProviderMapping()[provider]
|
|
||||||
if !ok {
|
|
||||||
return nil, warnings, fmt.Errorf("DNS provider %q does not have associated data", provider)
|
|
||||||
} else if !providerData.SupportsTLS {
|
|
||||||
return nil, warnings, fmt.Errorf("DNS provider %q does not support DNS over TLS", provider)
|
|
||||||
}
|
|
||||||
for _, IP := range providerData.IPs {
|
|
||||||
forwardZoneLines = append(forwardZoneLines,
|
|
||||||
fmt.Sprintf(" forward-addr: %s@853#%s", IP.String(), providerData.Host))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lines = append(lines, forwardZoneLines...)
|
|
||||||
return lines, warnings, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildBlocked(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
|
|
||||||
allowedHostnames, privateAddresses []string) (hostnamesLines, ipsLines []string, errs []error) {
|
|
||||||
chHostnames := make(chan []string)
|
|
||||||
chIPs := make(chan []string)
|
|
||||||
chErrors := make(chan []error)
|
|
||||||
go func() {
|
|
||||||
lines, errs := buildBlockedHostnames(client, blockMalicious, blockAds, blockSurveillance, allowedHostnames)
|
|
||||||
chHostnames <- lines
|
|
||||||
chErrors <- errs
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
lines, errs := buildBlockedIPs(client, blockMalicious, blockAds, blockSurveillance, privateAddresses)
|
|
||||||
chIPs <- lines
|
|
||||||
chErrors <- errs
|
|
||||||
}()
|
|
||||||
n := 2
|
|
||||||
for n > 0 {
|
|
||||||
select {
|
|
||||||
case lines := <-chHostnames:
|
|
||||||
hostnamesLines = append(hostnamesLines, lines...)
|
|
||||||
case lines := <-chIPs:
|
|
||||||
ipsLines = append(ipsLines, lines...)
|
|
||||||
case routineErrs := <-chErrors:
|
|
||||||
errs = append(errs, routineErrs...)
|
|
||||||
n--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hostnamesLines, ipsLines, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
func getList(client network.Client, URL string) (results []string, err error) {
|
|
||||||
content, status, err := client.GetContent(URL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if status != 200 {
|
|
||||||
return nil, fmt.Errorf("HTTP status code is %d and not 200", status)
|
|
||||||
}
|
|
||||||
results = strings.Split(string(content), "\n")
|
|
||||||
|
|
||||||
// remove empty lines
|
|
||||||
last := len(results) - 1
|
|
||||||
for i := range results {
|
|
||||||
if len(results[i]) == 0 {
|
|
||||||
results[i] = results[last]
|
|
||||||
last--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results = results[:last+1]
|
|
||||||
|
|
||||||
if len(results) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildBlockedHostnames(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
|
|
||||||
allowedHostnames []string) (lines []string, errs []error) {
|
|
||||||
chResults := make(chan []string)
|
|
||||||
chError := make(chan error)
|
|
||||||
listsLeftToFetch := 0
|
|
||||||
if blockMalicious {
|
|
||||||
listsLeftToFetch++
|
|
||||||
go func() {
|
|
||||||
results, err := getList(client, string(constants.MaliciousBlockListHostnamesURL))
|
|
||||||
chResults <- results
|
|
||||||
chError <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
if blockAds {
|
|
||||||
listsLeftToFetch++
|
|
||||||
go func() {
|
|
||||||
results, err := getList(client, string(constants.AdsBlockListHostnamesURL))
|
|
||||||
chResults <- results
|
|
||||||
chError <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
if blockSurveillance {
|
|
||||||
listsLeftToFetch++
|
|
||||||
go func() {
|
|
||||||
results, err := getList(client, string(constants.SurveillanceBlockListHostnamesURL))
|
|
||||||
chResults <- results
|
|
||||||
chError <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
uniqueResults := make(map[string]struct{})
|
|
||||||
for listsLeftToFetch > 0 {
|
|
||||||
select {
|
|
||||||
case results := <-chResults:
|
|
||||||
for _, result := range results {
|
|
||||||
uniqueResults[result] = struct{}{}
|
|
||||||
}
|
|
||||||
case err := <-chError:
|
|
||||||
listsLeftToFetch--
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, allowedHostname := range allowedHostnames {
|
|
||||||
delete(uniqueResults, allowedHostname)
|
|
||||||
}
|
|
||||||
for result := range uniqueResults {
|
|
||||||
lines = append(lines, " local-zone: \""+result+"\" static")
|
|
||||||
}
|
|
||||||
return lines, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildBlockedIPs(client network.Client, blockMalicious, blockAds, blockSurveillance bool,
|
|
||||||
privateAddresses []string) (lines []string, errs []error) {
|
|
||||||
chResults := make(chan []string)
|
|
||||||
chError := make(chan error)
|
|
||||||
listsLeftToFetch := 0
|
|
||||||
if blockMalicious {
|
|
||||||
listsLeftToFetch++
|
|
||||||
go func() {
|
|
||||||
results, err := getList(client, string(constants.MaliciousBlockListIPsURL))
|
|
||||||
chResults <- results
|
|
||||||
chError <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
if blockAds {
|
|
||||||
listsLeftToFetch++
|
|
||||||
go func() {
|
|
||||||
results, err := getList(client, string(constants.AdsBlockListIPsURL))
|
|
||||||
chResults <- results
|
|
||||||
chError <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
if blockSurveillance {
|
|
||||||
listsLeftToFetch++
|
|
||||||
go func() {
|
|
||||||
results, err := getList(client, string(constants.SurveillanceBlockListIPsURL))
|
|
||||||
chResults <- results
|
|
||||||
chError <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
uniqueResults := make(map[string]struct{})
|
|
||||||
for listsLeftToFetch > 0 {
|
|
||||||
select {
|
|
||||||
case results := <-chResults:
|
|
||||||
for _, result := range results {
|
|
||||||
uniqueResults[result] = struct{}{}
|
|
||||||
}
|
|
||||||
case err := <-chError:
|
|
||||||
listsLeftToFetch--
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, privateAddress := range privateAddresses {
|
|
||||||
uniqueResults[privateAddress] = struct{}{}
|
|
||||||
}
|
|
||||||
for result := range uniqueResults {
|
|
||||||
lines = append(lines, " private-address: "+result)
|
|
||||||
}
|
|
||||||
return lines, errs
|
|
||||||
}
|
|
||||||
@@ -1,520 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/qdm12/golibs/logging"
|
|
||||||
"github.com/qdm12/golibs/network/mocks"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/settings"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_generateUnboundConf(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
settings := settings.DNS{
|
|
||||||
Providers: []models.DNSProvider{constants.Cloudflare, constants.Quad9},
|
|
||||||
AllowedHostnames: []string{"a"},
|
|
||||||
PrivateAddresses: []string{"9.9.9.9"},
|
|
||||||
BlockMalicious: true,
|
|
||||||
BlockSurveillance: false,
|
|
||||||
BlockAds: false,
|
|
||||||
VerbosityLevel: 2,
|
|
||||||
ValidationLogLevel: 3,
|
|
||||||
Caching: true,
|
|
||||||
}
|
|
||||||
client := &mocks.Client{}
|
|
||||||
client.On("GetContent", string(constants.MaliciousBlockListHostnamesURL)).
|
|
||||||
Return([]byte("b\na\nc"), 200, nil).Once()
|
|
||||||
client.On("GetContent", string(constants.MaliciousBlockListIPsURL)).
|
|
||||||
Return([]byte("c\nd\n"), 200, nil).Once()
|
|
||||||
emptyLogger, err := logging.NewEmptyLogger()
|
|
||||||
require.NoError(t, err)
|
|
||||||
lines, warnings, err := generateUnboundConf(settings, client, emptyLogger)
|
|
||||||
require.Len(t, warnings, 0)
|
|
||||||
require.NoError(t, err)
|
|
||||||
client.AssertExpectations(t)
|
|
||||||
expected := `
|
|
||||||
server:
|
|
||||||
cache-max-ttl: 9000
|
|
||||||
cache-min-ttl: 3600
|
|
||||||
do-ip4: yes
|
|
||||||
do-ip6: no
|
|
||||||
harden-algo-downgrade: yes
|
|
||||||
harden-below-nxdomain: yes
|
|
||||||
harden-referral-path: yes
|
|
||||||
hide-identity: yes
|
|
||||||
hide-version: yes
|
|
||||||
interface: 127.0.0.1
|
|
||||||
key-cache-size: 16m
|
|
||||||
key-cache-slabs: 4
|
|
||||||
msg-cache-size: 4m
|
|
||||||
msg-cache-slabs: 4
|
|
||||||
num-threads: 1
|
|
||||||
port: 53
|
|
||||||
prefetch-key: yes
|
|
||||||
prefetch: yes
|
|
||||||
root-hints: "/etc/unbound/root.hints"
|
|
||||||
rrset-cache-size: 4m
|
|
||||||
rrset-cache-slabs: 4
|
|
||||||
rrset-roundrobin: yes
|
|
||||||
tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"
|
|
||||||
trust-anchor-file: "/etc/unbound/root.key"
|
|
||||||
use-syslog: no
|
|
||||||
username: "nonrootuser"
|
|
||||||
val-log-level: 3
|
|
||||||
verbosity: 2
|
|
||||||
local-zone: "b" static
|
|
||||||
local-zone: "c" static
|
|
||||||
private-address: 9.9.9.9
|
|
||||||
private-address: c
|
|
||||||
private-address: d
|
|
||||||
forward-zone:
|
|
||||||
forward-no-cache: no
|
|
||||||
forward-tls-upstream: yes
|
|
||||||
name: "."
|
|
||||||
forward-addr: 1.1.1.1@853#cloudflare-dns.com
|
|
||||||
forward-addr: 1.0.0.1@853#cloudflare-dns.com
|
|
||||||
forward-addr: 9.9.9.9@853#dns.quad9.net
|
|
||||||
forward-addr: 149.112.112.112@853#dns.quad9.net`
|
|
||||||
assert.Equal(t, expected, "\n"+strings.Join(lines, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_buildBlocked(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
type blockParams struct {
|
|
||||||
blocked bool
|
|
||||||
content []byte
|
|
||||||
clientErr error
|
|
||||||
}
|
|
||||||
tests := map[string]struct {
|
|
||||||
malicious blockParams
|
|
||||||
ads blockParams
|
|
||||||
surveillance blockParams
|
|
||||||
allowedHostnames []string
|
|
||||||
privateAddresses []string
|
|
||||||
hostnamesLines []string
|
|
||||||
ipsLines []string
|
|
||||||
errsString []string
|
|
||||||
}{
|
|
||||||
"none blocked": {},
|
|
||||||
"all blocked without lists": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"all blocked with lists": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("malicious"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("ads"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("surveillance"),
|
|
||||||
},
|
|
||||||
hostnamesLines: []string{
|
|
||||||
" local-zone: \"ads\" static",
|
|
||||||
" local-zone: \"malicious\" static",
|
|
||||||
" local-zone: \"surveillance\" static"},
|
|
||||||
ipsLines: []string{
|
|
||||||
" private-address: ads",
|
|
||||||
" private-address: malicious",
|
|
||||||
" private-address: surveillance"},
|
|
||||||
},
|
|
||||||
"all blocked with allowed hostnames": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("malicious"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("ads"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("surveillance"),
|
|
||||||
},
|
|
||||||
allowedHostnames: []string{"ads"},
|
|
||||||
hostnamesLines: []string{
|
|
||||||
" local-zone: \"malicious\" static",
|
|
||||||
" local-zone: \"surveillance\" static"},
|
|
||||||
ipsLines: []string{
|
|
||||||
" private-address: ads",
|
|
||||||
" private-address: malicious",
|
|
||||||
" private-address: surveillance"},
|
|
||||||
},
|
|
||||||
"all blocked with private addresses": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("malicious"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("ads"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("surveillance"),
|
|
||||||
},
|
|
||||||
privateAddresses: []string{"ads", "192.100.1.5"},
|
|
||||||
hostnamesLines: []string{
|
|
||||||
" local-zone: \"ads\" static",
|
|
||||||
" local-zone: \"malicious\" static",
|
|
||||||
" local-zone: \"surveillance\" static"},
|
|
||||||
ipsLines: []string{
|
|
||||||
" private-address: 192.100.1.5",
|
|
||||||
" private-address: ads",
|
|
||||||
" private-address: malicious",
|
|
||||||
" private-address: surveillance"},
|
|
||||||
},
|
|
||||||
"all blocked with lists and one error": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("malicious"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("ads"),
|
|
||||||
clientErr: fmt.Errorf("ads error"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("surveillance"),
|
|
||||||
},
|
|
||||||
hostnamesLines: []string{
|
|
||||||
" local-zone: \"malicious\" static",
|
|
||||||
" local-zone: \"surveillance\" static"},
|
|
||||||
ipsLines: []string{
|
|
||||||
" private-address: malicious",
|
|
||||||
" private-address: surveillance"},
|
|
||||||
errsString: []string{"ads error", "ads error"},
|
|
||||||
},
|
|
||||||
"all blocked with errors": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
clientErr: fmt.Errorf("malicious"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
clientErr: fmt.Errorf("ads"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
clientErr: fmt.Errorf("surveillance"),
|
|
||||||
},
|
|
||||||
errsString: []string{"malicious", "malicious", "ads", "ads", "surveillance", "surveillance"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
client := &mocks.Client{}
|
|
||||||
if tc.malicious.blocked {
|
|
||||||
client.On("GetContent", string(constants.MaliciousBlockListHostnamesURL)).
|
|
||||||
Return(tc.malicious.content, 200, tc.malicious.clientErr).Once()
|
|
||||||
client.On("GetContent", string(constants.MaliciousBlockListIPsURL)).
|
|
||||||
Return(tc.malicious.content, 200, tc.malicious.clientErr).Once()
|
|
||||||
}
|
|
||||||
if tc.ads.blocked {
|
|
||||||
client.On("GetContent", string(constants.AdsBlockListHostnamesURL)).
|
|
||||||
Return(tc.ads.content, 200, tc.ads.clientErr).Once()
|
|
||||||
client.On("GetContent", string(constants.AdsBlockListIPsURL)).
|
|
||||||
Return(tc.ads.content, 200, tc.ads.clientErr).Once()
|
|
||||||
}
|
|
||||||
if tc.surveillance.blocked {
|
|
||||||
client.On("GetContent", string(constants.SurveillanceBlockListHostnamesURL)).
|
|
||||||
Return(tc.surveillance.content, 200, tc.surveillance.clientErr).Once()
|
|
||||||
client.On("GetContent", string(constants.SurveillanceBlockListIPsURL)).
|
|
||||||
Return(tc.surveillance.content, 200, tc.surveillance.clientErr).Once()
|
|
||||||
}
|
|
||||||
hostnamesLines, ipsLines, errs := buildBlocked(client, tc.malicious.blocked, tc.ads.blocked, tc.surveillance.blocked,
|
|
||||||
tc.allowedHostnames, tc.privateAddresses)
|
|
||||||
var errsString []string
|
|
||||||
for _, err := range errs {
|
|
||||||
errsString = append(errsString, err.Error())
|
|
||||||
}
|
|
||||||
assert.ElementsMatch(t, tc.errsString, errsString)
|
|
||||||
assert.ElementsMatch(t, tc.hostnamesLines, hostnamesLines)
|
|
||||||
assert.ElementsMatch(t, tc.ipsLines, ipsLines)
|
|
||||||
client.AssertExpectations(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getList(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
tests := map[string]struct {
|
|
||||||
content []byte
|
|
||||||
status int
|
|
||||||
clientErr error
|
|
||||||
results []string
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
"no result": {nil, 200, nil, nil, nil},
|
|
||||||
"bad status": {nil, 500, nil, nil, fmt.Errorf("HTTP status code is 500 and not 200")},
|
|
||||||
"network error": {nil, 200, fmt.Errorf("error"), nil, fmt.Errorf("error")},
|
|
||||||
"results": {[]byte("a\nb\nc\n"), 200, nil, []string{"a", "b", "c"}, nil},
|
|
||||||
}
|
|
||||||
for name, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
client := &mocks.Client{}
|
|
||||||
client.On("GetContent", "irrelevant_url").Return(
|
|
||||||
tc.content, tc.status, tc.clientErr,
|
|
||||||
).Once()
|
|
||||||
results, err := getList(client, "irrelevant_url")
|
|
||||||
if tc.err != nil {
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Equal(t, tc.err.Error(), err.Error())
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
assert.Equal(t, tc.results, results)
|
|
||||||
client.AssertExpectations(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_buildBlockedHostnames(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
type blockParams struct {
|
|
||||||
blocked bool
|
|
||||||
content []byte
|
|
||||||
clientErr error
|
|
||||||
}
|
|
||||||
tests := map[string]struct {
|
|
||||||
malicious blockParams
|
|
||||||
ads blockParams
|
|
||||||
surveillance blockParams
|
|
||||||
allowedHostnames []string
|
|
||||||
lines []string
|
|
||||||
errsString []string
|
|
||||||
}{
|
|
||||||
"nothing blocked": {
|
|
||||||
lines: nil,
|
|
||||||
errsString: nil,
|
|
||||||
},
|
|
||||||
"only malicious blocked": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
clientErr: nil,
|
|
||||||
},
|
|
||||||
lines: []string{
|
|
||||||
" local-zone: \"site_a\" static",
|
|
||||||
" local-zone: \"site_b\" static"},
|
|
||||||
errsString: nil,
|
|
||||||
},
|
|
||||||
"all blocked with some duplicates": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_c"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_c\nsite_a"),
|
|
||||||
},
|
|
||||||
lines: []string{
|
|
||||||
" local-zone: \"site_a\" static",
|
|
||||||
" local-zone: \"site_b\" static",
|
|
||||||
" local-zone: \"site_c\" static"},
|
|
||||||
errsString: nil,
|
|
||||||
},
|
|
||||||
"all blocked with one errored": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_c"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
clientErr: fmt.Errorf("surveillance error"),
|
|
||||||
},
|
|
||||||
lines: []string{
|
|
||||||
" local-zone: \"site_a\" static",
|
|
||||||
" local-zone: \"site_b\" static",
|
|
||||||
" local-zone: \"site_c\" static"},
|
|
||||||
errsString: []string{"surveillance error"},
|
|
||||||
},
|
|
||||||
"blocked with allowed hostnames": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_c\nsite_d"),
|
|
||||||
},
|
|
||||||
allowedHostnames: []string{"site_b", "site_c"},
|
|
||||||
lines: []string{
|
|
||||||
" local-zone: \"site_a\" static",
|
|
||||||
" local-zone: \"site_d\" static"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
client := &mocks.Client{}
|
|
||||||
if tc.malicious.blocked {
|
|
||||||
client.On("GetContent", string(constants.MaliciousBlockListHostnamesURL)).
|
|
||||||
Return(tc.malicious.content, 200, tc.malicious.clientErr).Once()
|
|
||||||
}
|
|
||||||
if tc.ads.blocked {
|
|
||||||
client.On("GetContent", string(constants.AdsBlockListHostnamesURL)).
|
|
||||||
Return(tc.ads.content, 200, tc.ads.clientErr).Once()
|
|
||||||
}
|
|
||||||
if tc.surveillance.blocked {
|
|
||||||
client.On("GetContent", string(constants.SurveillanceBlockListHostnamesURL)).
|
|
||||||
Return(tc.surveillance.content, 200, tc.surveillance.clientErr).Once()
|
|
||||||
}
|
|
||||||
lines, errs := buildBlockedHostnames(client,
|
|
||||||
tc.malicious.blocked, tc.ads.blocked, tc.surveillance.blocked, tc.allowedHostnames)
|
|
||||||
var errsString []string
|
|
||||||
for _, err := range errs {
|
|
||||||
errsString = append(errsString, err.Error())
|
|
||||||
}
|
|
||||||
assert.ElementsMatch(t, tc.errsString, errsString)
|
|
||||||
assert.ElementsMatch(t, tc.lines, lines)
|
|
||||||
client.AssertExpectations(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_buildBlockedIPs(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
type blockParams struct {
|
|
||||||
blocked bool
|
|
||||||
content []byte
|
|
||||||
clientErr error
|
|
||||||
}
|
|
||||||
tests := map[string]struct {
|
|
||||||
malicious blockParams
|
|
||||||
ads blockParams
|
|
||||||
surveillance blockParams
|
|
||||||
privateAddresses []string
|
|
||||||
lines []string
|
|
||||||
errsString []string
|
|
||||||
}{
|
|
||||||
"nothing blocked": {
|
|
||||||
lines: nil,
|
|
||||||
errsString: nil,
|
|
||||||
},
|
|
||||||
"only malicious blocked": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
clientErr: nil,
|
|
||||||
},
|
|
||||||
lines: []string{
|
|
||||||
" private-address: site_a",
|
|
||||||
" private-address: site_b"},
|
|
||||||
errsString: nil,
|
|
||||||
},
|
|
||||||
"all blocked with some duplicates": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_c"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_c\nsite_a"),
|
|
||||||
},
|
|
||||||
lines: []string{
|
|
||||||
" private-address: site_a",
|
|
||||||
" private-address: site_b",
|
|
||||||
" private-address: site_c"},
|
|
||||||
errsString: nil,
|
|
||||||
},
|
|
||||||
"all blocked with one errored": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_c"),
|
|
||||||
},
|
|
||||||
surveillance: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
clientErr: fmt.Errorf("surveillance error"),
|
|
||||||
},
|
|
||||||
lines: []string{
|
|
||||||
" private-address: site_a",
|
|
||||||
" private-address: site_b",
|
|
||||||
" private-address: site_c"},
|
|
||||||
errsString: []string{"surveillance error"},
|
|
||||||
},
|
|
||||||
"blocked with private addresses": {
|
|
||||||
malicious: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_a\nsite_b"),
|
|
||||||
},
|
|
||||||
ads: blockParams{
|
|
||||||
blocked: true,
|
|
||||||
content: []byte("site_c"),
|
|
||||||
},
|
|
||||||
privateAddresses: []string{"site_c", "site_d"},
|
|
||||||
lines: []string{
|
|
||||||
" private-address: site_a",
|
|
||||||
" private-address: site_b",
|
|
||||||
" private-address: site_c",
|
|
||||||
" private-address: site_d"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
client := &mocks.Client{}
|
|
||||||
if tc.malicious.blocked {
|
|
||||||
client.On("GetContent", string(constants.MaliciousBlockListIPsURL)).
|
|
||||||
Return(tc.malicious.content, 200, tc.malicious.clientErr).Once()
|
|
||||||
}
|
|
||||||
if tc.ads.blocked {
|
|
||||||
client.On("GetContent", string(constants.AdsBlockListIPsURL)).
|
|
||||||
Return(tc.ads.content, 200, tc.ads.clientErr).Once()
|
|
||||||
}
|
|
||||||
if tc.surveillance.blocked {
|
|
||||||
client.On("GetContent", string(constants.SurveillanceBlockListIPsURL)).
|
|
||||||
Return(tc.surveillance.content, 200, tc.surveillance.clientErr).Once()
|
|
||||||
}
|
|
||||||
lines, errs := buildBlockedIPs(client,
|
|
||||||
tc.malicious.blocked, tc.ads.blocked, tc.surveillance.blocked, tc.privateAddresses)
|
|
||||||
var errsString []string
|
|
||||||
for _, err := range errs {
|
|
||||||
errsString = append(errsString, err.Error())
|
|
||||||
}
|
|
||||||
assert.ElementsMatch(t, tc.errsString, errsString)
|
|
||||||
assert.ElementsMatch(t, tc.lines, lines)
|
|
||||||
client.AssertExpectations(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/qdm12/golibs/command"
|
|
||||||
"github.com/qdm12/golibs/files"
|
|
||||||
"github.com/qdm12/golibs/logging"
|
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
"github.com/qdm12/private-internet-access-docker/internal/settings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const logPrefix = "dns configurator"
|
|
||||||
|
|
||||||
type Configurator interface {
|
|
||||||
DownloadRootHints(uid, gid int) error
|
|
||||||
DownloadRootKey(uid, gid int) error
|
|
||||||
MakeUnboundConf(settings settings.DNS, uid, gid int) (err error)
|
|
||||||
UseDNSInternally(IP net.IP)
|
|
||||||
UseDNSSystemWide(IP net.IP) error
|
|
||||||
Start(logLevel uint8) (stdout io.ReadCloser, waitFn func() error, err error)
|
|
||||||
WaitForUnbound() (err error)
|
|
||||||
Version() (version string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type configurator struct {
|
|
||||||
logger logging.Logger
|
|
||||||
client network.Client
|
|
||||||
fileManager files.FileManager
|
|
||||||
commander command.Commander
|
|
||||||
lookupIP func(host string) ([]net.IP, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfigurator(logger logging.Logger, client network.Client, fileManager files.FileManager) Configurator {
|
|
||||||
return &configurator{
|
|
||||||
logger: logger,
|
|
||||||
client: client,
|
|
||||||
fileManager: fileManager,
|
|
||||||
commander: command.NewCommander(),
|
|
||||||
lookupIP: net.LookupIP,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
61
internal/dns/logs.go
Normal file
61
internal/dns/logs.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *looper) collectLines(wg *sync.WaitGroup, stdout, stderr <-chan string) {
|
||||||
|
defer wg.Done()
|
||||||
|
var line string
|
||||||
|
var ok bool
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case line, ok = <-stderr:
|
||||||
|
case line, ok = <-stdout:
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
line, level := processLogLine(line)
|
||||||
|
switch level {
|
||||||
|
case logging.DebugLevel:
|
||||||
|
l.logger.Debug(line)
|
||||||
|
case logging.InfoLevel:
|
||||||
|
l.logger.Info(line)
|
||||||
|
case logging.WarnLevel:
|
||||||
|
l.logger.Warn(line)
|
||||||
|
case logging.ErrorLevel:
|
||||||
|
l.logger.Error(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var unboundPrefix = regexp.MustCompile(`\[[0-9]{10}\] unbound\[[0-9]+:[0|1]\] `)
|
||||||
|
|
||||||
|
func processLogLine(s string) (filtered string, level logging.Level) {
|
||||||
|
prefix := unboundPrefix.FindString(s)
|
||||||
|
filtered = s[len(prefix):]
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(filtered, "notice: "):
|
||||||
|
filtered = strings.TrimPrefix(filtered, "notice: ")
|
||||||
|
level = logging.InfoLevel
|
||||||
|
case strings.HasPrefix(filtered, "info: "):
|
||||||
|
filtered = strings.TrimPrefix(filtered, "info: ")
|
||||||
|
level = logging.InfoLevel
|
||||||
|
case strings.HasPrefix(filtered, "warn: "):
|
||||||
|
filtered = strings.TrimPrefix(filtered, "warn: ")
|
||||||
|
level = logging.WarnLevel
|
||||||
|
case strings.HasPrefix(filtered, "error: "):
|
||||||
|
filtered = strings.TrimPrefix(filtered, "error: ")
|
||||||
|
level = logging.ErrorLevel
|
||||||
|
default:
|
||||||
|
level = logging.InfoLevel
|
||||||
|
}
|
||||||
|
filtered = constants.ColorUnbound().Sprintf(filtered)
|
||||||
|
return filtered, level
|
||||||
|
}
|
||||||
49
internal/dns/logs_test.go
Normal file
49
internal/dns/logs_test.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_processLogLine(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tests := map[string]struct {
|
||||||
|
s string
|
||||||
|
filtered string
|
||||||
|
level logging.Level
|
||||||
|
}{
|
||||||
|
"empty string": {"", "", logging.InfoLevel},
|
||||||
|
"random string": {"asdasqdb", "asdasqdb", logging.InfoLevel},
|
||||||
|
"unbound notice": {
|
||||||
|
"[1594595249] unbound[75:0] notice: init module 0: validator",
|
||||||
|
"init module 0: validator",
|
||||||
|
logging.InfoLevel},
|
||||||
|
"unbound info": {
|
||||||
|
"[1594595249] unbound[75:0] info: init module 0: validator",
|
||||||
|
"init module 0: validator",
|
||||||
|
logging.InfoLevel},
|
||||||
|
"unbound warn": {
|
||||||
|
"[1594595249] unbound[75:0] warn: init module 0: validator",
|
||||||
|
"init module 0: validator",
|
||||||
|
logging.WarnLevel},
|
||||||
|
"unbound error": {
|
||||||
|
"[1594595249] unbound[75:0] error: init module 0: validator",
|
||||||
|
"init module 0: validator",
|
||||||
|
logging.ErrorLevel},
|
||||||
|
"unbound unknown": {
|
||||||
|
"[1594595249] unbound[75:0] BLA: init module 0: validator",
|
||||||
|
"BLA: init module 0: validator",
|
||||||
|
logging.InfoLevel},
|
||||||
|
}
|
||||||
|
for name, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
filtered, level := processLogLine(tc.s)
|
||||||
|
assert.Equal(t, tc.filtered, filtered)
|
||||||
|
assert.Equal(t, tc.level, level)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user