Skip to content

Commit 2c2a3ab

Browse files
committed
Add option to enable gost metrics and prepare roles for users.
1 parent 468216a commit 2c2a3ab

6 files changed

Lines changed: 87 additions & 12 deletions

File tree

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ HEALTHCHECK --interval=15s --timeout=5s --retries=3 --start-period=10s CMD \
3434
sh -c "curl -fs https://am.i.mullvad.net/json | grep -q '\"mullvad_exit_ip\":true'"
3535

3636
# TCP 1080 = local proxy
37+
# TCP 9100 = Prometheus Metrics
3738
# TCP 2000-3000 = Mullvad City proxies
38-
EXPOSE 1080 2000-3000
39+
EXPOSE 1080 9100 2000-3000
3940

4041
VOLUME ["/data"]
4142
CMD [ "/run.sh" ]

GostGen/source/GatewayConfig.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ internal record GatewayConfig
4747
/// </summary>
4848
public GostLogLevel GostLogLevel { get; set; } = GostLogLevel.warn;
4949

50+
/// <summary>
51+
/// Gets or sets a value indicating whether metrics for gost are enabled.
52+
/// </summary>
53+
public bool GostMetricsEnabled { get; set; }
54+
5055
/// <summary>
5156
/// Gets or sets the users.
5257
/// </summary>
@@ -148,6 +153,21 @@ public record User
148153
/// Gets or sets the password.
149154
/// </summary>
150155
public string Password { get; set; } = null!;
156+
157+
/// <summary>
158+
/// Gets or sets a value indicating whether the user has access to mullvad proxies.
159+
/// </summary>
160+
public bool HasMullvadProxyAccess { get; set; } = true;
161+
162+
/// <summary>
163+
/// Gets or sets a value indicating whether the user has access to the internal proxy.
164+
/// </summary>
165+
public bool HasInternalProxyAccess { get; set; }
166+
167+
/// <summary>
168+
/// Gets or sets a value indicating whether the user has access to the metrics server.
169+
/// </summary>
170+
public bool HasMetricsAccess { get; set; }
151171
}
152172

153173
/// <summary>

GostGen/source/GostConfig.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ internal record GostConfig
2121
[YamlMember(Alias = "log")]
2222
public LogConfig? Log { get; set; }
2323

24+
[YamlMember(Alias = "metrics")]
25+
public MetricsConfig? Metrics { get; set; }
26+
2427
[YamlMember(Alias = "authers")]
2528
public List<AutherConfig>? Authers { get; set; }
2629

@@ -81,9 +84,6 @@ internal record GostConfig
8184
//[YamlMember(Alias = "api")]
8285
//public ApiConfig? API { get; set; }
8386

84-
//[YamlMember(Alias = "metrics")]
85-
//public MetricsConfig? Metrics { get; set; }
86-
8787
/// <summary>
8888
/// Loads the config from the given text.
8989
/// </summary>

GostGen/source/Program.cs

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ public class Program
2525
{
2626
private const string ExportCsvFile = "data/proxies.csv";
2727
private const string ExportJsonFile = "data/proxies.json";
28+
private const string AutherMetricsGroup = "auther-metrics";
29+
private const string AutherInternalGroup = "auther-internal";
2830
private const string AutherMullvadGroup = "auther-mullvad";
2931
private const string BypassMullvadGroup = "bypass-mullvad";
3032
private const string ServiceLocalName = "service-local";
3133
private const string SocksType = "socks5";
3234
private const string NetworkProtocol = "tcp";
35+
private const string MetricsPath = "/metrics";
3336

37+
private const int MetricsPort = 9100;
3438
private const int ProxyPortLocal = 1080;
3539
private const int ProxyPortCitiesStart = 2000;
3640
private const int ProxyPortCitiesEnd = 3000;
@@ -69,6 +73,7 @@ public static async Task Main(string[] args)
6973
var cfgChanged = await UpdateGostLoggingAsync(gostConfig);
7074
cfgChanged |= await UpdateUsersAsync(gostConfig);
7175
cfgChanged |= await UpdateBypassesAsync(gostConfig);
76+
cfgChanged |= await UpdateMetricsServerAsync(gostConfig);
7277
cfgChanged |= await UpdateLocalProxyAsync(gostConfig);
7378
cfgChanged |= await UpdateGostServersAsync(gostConfig);
7479

@@ -229,14 +234,37 @@ private static Task<bool> UpdateUsersAsync(GostConfig gostConfig)
229234
changed = true;
230235
}
231236

237+
var internalGroup = gostConfig.Authers.FirstOrDefault(a => string.Equals(a.Name, AutherInternalGroup));
238+
if (internalGroup == null)
239+
{
240+
Log.Debug($"Adding auther group `{AutherInternalGroup}`");
241+
internalGroup = new AutherConfig { Name = AutherInternalGroup };
242+
gostConfig.Authers.Add(internalGroup);
243+
changed = true;
244+
}
245+
246+
var metricsGroup = gostConfig.Authers.FirstOrDefault(a => string.Equals(a.Name, AutherMetricsGroup));
247+
if (metricsGroup == null)
248+
{
249+
Log.Debug($"Adding auther group `{AutherMetricsGroup}`");
250+
metricsGroup = new AutherConfig { Name = AutherMetricsGroup };
251+
gostConfig.Authers.Add(metricsGroup);
252+
changed = true;
253+
}
254+
232255
mullvadGroup.Auths ??= [];
256+
internalGroup.Auths ??= [];
257+
metricsGroup.Auths ??= [];
233258
foreach (var configUser in _gatewayConfig.Users)
234259
{
260+
// ToDo add users inside configured auth groups depending on user role
235261
var gostUser = mullvadGroup.Auths.FirstOrDefault(u => string.Equals(u.Username, configUser.Key));
236262
if (gostUser == null)
237263
{
238264
Log.Debug($"Add new user `{configUser.Key}` to `{AutherMullvadGroup}`");
239265
mullvadGroup.Auths.Add(new AuthConfig { Username = configUser.Key, Password = configUser.Value.Password });
266+
internalGroup.Auths.Add(new AuthConfig { Username = configUser.Key, Password = configUser.Value.Password });
267+
metricsGroup.Auths.Add(new AuthConfig { Username = configUser.Key, Password = configUser.Value.Password });
240268
changed = true;
241269
continue;
242270
}
@@ -252,7 +280,7 @@ private static Task<bool> UpdateUsersAsync(GostConfig gostConfig)
252280
foreach (var gostAuth in mullvadGroup.Auths.ToArray())
253281
{
254282
if (!string.IsNullOrWhiteSpace(gostAuth.Username) &&
255-
_gatewayConfig.Users.ContainsKey(gostAuth.Username))
283+
_gatewayConfig.Users.ContainsKey(gostAuth.Username))
256284
continue;
257285

258286
Log.Debug($"Removing user `{gostAuth.Username}` from `{AutherMullvadGroup}`");
@@ -301,6 +329,34 @@ private static Task<bool> UpdateBypassesAsync(GostConfig gostConfig)
301329
return Task.FromResult(changed);
302330
}
303331

332+
private static Task<bool> UpdateMetricsServerAsync(GostConfig gostConfig)
333+
{
334+
var changed = false;
335+
if (_gatewayConfig.GostMetricsEnabled)
336+
{
337+
var metricsAddress = $":{MetricsPort}";
338+
gostConfig.Metrics ??= new();
339+
if (gostConfig.Metrics.Addr != metricsAddress ||
340+
!string.Equals(gostConfig.Metrics.Path, MetricsPath) ||
341+
!string.Equals(gostConfig.Metrics.Auther, AutherMetricsGroup))
342+
{
343+
Log.Debug($"Enable metrics server at `user:pass@ip:{MetricsPort}?path=/metrics`");
344+
gostConfig.Metrics.Addr = metricsAddress;
345+
gostConfig.Metrics.Path = MetricsPath;
346+
gostConfig.Metrics.Auther = AutherMetricsGroup;
347+
changed = true;
348+
}
349+
}
350+
else if (gostConfig.Metrics != null)
351+
{
352+
Log.Debug($"Disable metrics server at `user:pass@ip:{MetricsPort}?path=/metrics`");
353+
gostConfig.Metrics = null;
354+
changed = true;
355+
}
356+
357+
return Task.FromResult(changed);
358+
}
359+
304360
private static Task<bool> UpdateLocalProxyAsync(GostConfig gostConfig)
305361
{
306362
var changed = false;
@@ -317,13 +373,13 @@ private static Task<bool> UpdateLocalProxyAsync(GostConfig gostConfig)
317373
!string.Equals(service.Interface, InputInterfaceName) ||
318374
!string.Equals(service.Listener?.Type, NetworkProtocol) ||
319375
!string.Equals(service.Handler?.Type, SocksType) ||
320-
!string.Equals(service.Handler?.Auther, AutherMullvadGroup))
376+
!string.Equals(service.Handler?.Auther, AutherInternalGroup))
321377
{
322378
Log.Debug($"Updating local proxy configuration `{ServiceLocalName}`");
323379
service.Addr = address;
324380
service.Interface = InputInterfaceName;
325381
service.Listener = new() { Type = NetworkProtocol };
326-
service.Handler = new() { Type = SocksType, Auther = AutherMullvadGroup };
382+
service.Handler = new() { Type = SocksType, Auther = AutherInternalGroup };
327383
changed = true;
328384
}
329385

@@ -359,9 +415,9 @@ private static async Task<bool> UpdateGostServersAsync(GostConfig gostConfig)
359415
}
360416
}
361417

362-
if (cfgChanged || !File.Exists(ExportCsvFile) || new FileInfo(ExportCsvFile).Length < 1)
418+
if (cfgChanged || !File.Exists(ExportCsvFile) || new FileInfo(ExportCsvFile).Length < 1)
363419
ExportProxyCsv(proxies);
364-
if (cfgChanged || !File.Exists(ExportJsonFile) || new FileInfo(ExportJsonFile).Length < 1)
420+
if (cfgChanged || !File.Exists(ExportJsonFile) || new FileInfo(ExportJsonFile).Length < 1)
365421
ExportProxyJson(proxies);
366422

367423
return cfgChanged;

GostGen/source/Proxy.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
/// </summary>
66
internal record Proxy
77
{
8-
public Proxy() { }
9-
108
internal Proxy(bool isPool, MullvadRelay server, ServiceConfig service)
119
{
1210
IsPool = isPool;

debug.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ dotnet publish ${NET_PROJECT} -r linux-musl-x64 ${NET_BUILD_ARGS} -o ./GostGen/p
1212
dotnet publish ${NET_PROJECT} -r linux-musl-arm64 ${NET_BUILD_ARGS} -o ./GostGen/publish/linux/arm64/v8 && \
1313
docker buildx build --progress=plain --rm --platform linux/amd64,linux/arm/v7,linux/arm64/v8 -f ${DOCKER_FILE} -t ${IMAGE_NAME} . && \
1414
docker volume create mullvadproxygateway_data && \
15-
docker run --rm -it -v mullvadproxygateway_data:/data -p 1080:1080 -p 2000-3000:2000-3000 --cap-add NET_ADMIN --sysctl net.ipv4.conf.all.src_valid_mark=1 ${IMAGE_NAME}
15+
docker run --rm -it -v mullvadproxygateway_data:/data -p 1080:1080 -p 9100:9100 -p 2000-3000:2000-3000 --cap-add NET_ADMIN --sysctl net.ipv4.conf.all.src_valid_mark=1 ${IMAGE_NAME}

0 commit comments

Comments
 (0)