Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ COPY docker-entrypoint.sh /usr/local/bin/
COPY package*.json ./
COPY ./libs ./libs

RUN apk add --no-cache supervisor libnftnl libmnl && \
RUN apk add --no-cache \
bash \
curl \
iproute2 \
libmnl \
libnftnl \
openresolv \
supervisor \
wireguard-tools && \
mkdir -p /var/log/supervisor && \
chmod +x /usr/local/bin/docker-entrypoint.sh && \
ln -s /usr/local/bin/xray /usr/local/bin/rw-core
Expand All @@ -64,4 +72,4 @@ ENV XTLS_API_PORT=61000

ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]

CMD ["node", "dist/src/main"]
CMD ["node", "dist/src/main"]
2 changes: 2 additions & 0 deletions docker-compose-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ services:
restart: always
cap_add:
- NET_ADMIN
volumes:
- /etc/wireguard:/etc/wireguard
ulimits:
nofile:
soft: 1048576
Expand Down
1 change: 1 addition & 0 deletions libs/contract/api/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './handler';
export * from './plugin';
export * from './stats';
export * from './vision';
export * from './warp';
export * from './xray';
9 changes: 9 additions & 0 deletions libs/contract/api/controllers/warp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const WARP_CONTROLLER = 'warp' as const;

export const WARP_ROUTES = {
STATUS: 'status',
INSTALL: 'install',
ENABLE: 'enable',
DISABLE: 'disable',
UNINSTALL: 'uninstall',
} as const;
7 changes: 7 additions & 0 deletions libs/contract/api/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,11 @@ export const REST_API = {
RECREATE_TABLES: `${ROOT}/${CONTROLLERS.PLUGIN_CONTROLLER}/${CONTROLLERS.PLUGIN_ROUTES.NFTABLES.RECREATE_TABLES}`,
},
},
WARP: {
STATUS: `${ROOT}/${CONTROLLERS.WARP_CONTROLLER}/${CONTROLLERS.WARP_ROUTES.STATUS}`,
INSTALL: `${ROOT}/${CONTROLLERS.WARP_CONTROLLER}/${CONTROLLERS.WARP_ROUTES.INSTALL}`,
ENABLE: `${ROOT}/${CONTROLLERS.WARP_CONTROLLER}/${CONTROLLERS.WARP_ROUTES.ENABLE}`,
DISABLE: `${ROOT}/${CONTROLLERS.WARP_CONTROLLER}/${CONTROLLERS.WARP_ROUTES.DISABLE}`,
UNINSTALL: `${ROOT}/${CONTROLLERS.WARP_CONTROLLER}/${CONTROLLERS.WARP_ROUTES.UNINSTALL}`,
},
} as const;
1 change: 1 addition & 0 deletions libs/contract/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './handler';
export * from './plugin';
export * from './stats';
export * from './vision';
export * from './warp';
export * from './xray';
14 changes: 14 additions & 0 deletions libs/contract/commands/warp/disable.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from 'zod';

import { WarpStatusSchema } from '../../models';
import { REST_API } from '../../api';

export namespace DisableWarpCommand {
export const url = REST_API.WARP.DISABLE;

export const ResponseSchema = z.object({
response: WarpStatusSchema,
});

export type Response = z.infer<typeof ResponseSchema>;
}
14 changes: 14 additions & 0 deletions libs/contract/commands/warp/enable.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from 'zod';

import { WarpStatusSchema } from '../../models';
import { REST_API } from '../../api';

export namespace EnableWarpCommand {
export const url = REST_API.WARP.ENABLE;

export const ResponseSchema = z.object({
response: WarpStatusSchema,
});

export type Response = z.infer<typeof ResponseSchema>;
}
5 changes: 5 additions & 0 deletions libs/contract/commands/warp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './disable.command';
export * from './enable.command';
export * from './install.command';
export * from './status.command';
export * from './uninstall.command';
14 changes: 14 additions & 0 deletions libs/contract/commands/warp/install.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from 'zod';

import { WarpStatusSchema } from '../../models';
import { REST_API } from '../../api';

export namespace InstallWarpCommand {
export const url = REST_API.WARP.INSTALL;

export const ResponseSchema = z.object({
response: WarpStatusSchema,
});

export type Response = z.infer<typeof ResponseSchema>;
}
14 changes: 14 additions & 0 deletions libs/contract/commands/warp/status.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from 'zod';

import { WarpStatusSchema } from '../../models';
import { REST_API } from '../../api';

export namespace GetWarpStatusCommand {
export const url = REST_API.WARP.STATUS;

export const ResponseSchema = z.object({
response: WarpStatusSchema,
});

export type Response = z.infer<typeof ResponseSchema>;
}
14 changes: 14 additions & 0 deletions libs/contract/commands/warp/uninstall.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from 'zod';

import { WarpStatusSchema } from '../../models';
import { REST_API } from '../../api';

export namespace UninstallWarpCommand {
export const url = REST_API.WARP.UNINSTALL;

export const ResponseSchema = z.object({
response: WarpStatusSchema,
});

export type Response = z.infer<typeof ResponseSchema>;
}
52 changes: 52 additions & 0 deletions libs/contract/models/node-system.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,53 @@ export const NetworkInterfaceSchema = z.object({
txTotal: z.number(),
});

const WarpTraceSchema = z.object({
publicIp: z.string().nullable(),
countryCode: z.string().nullable(),
warp: z.enum(['on', 'off', 'unknown']),
colo: z.string().nullable(),
});

const PublicIpProbeSchema = z.object({
publicIp: z.string().nullable(),
countryCode: z.string().nullable(),
reachable: z.boolean(),
lastError: z.string().nullable(),
});

export const HostConnectivitySchema = z.object({
publicIpv4: z.string().nullable(),
publicIpv6: z.string().nullable(),
supportsIpv4: z.boolean(),
supportsIpv6: z.boolean(),
ipv4: PublicIpProbeSchema.nullable(),
ipv6: PublicIpProbeSchema.nullable(),
lastError: z.string().nullable(),
});

export const WarpOperationSchema = z.object({
state: z.enum(['idle', 'installing', 'enabling', 'disabling', 'uninstalling', 'error']),
startedAt: z.string().nullable(),
finishedAt: z.string().nullable(),
step: z.string().nullable(),
logs: z.array(z.string()),
});

export const WarpStatusSchema = z.object({
installed: z.boolean(),
running: z.boolean(),
interfaceName: z.string().nullable(),
publicIp: z.string().nullable(),
publicIpv4: z.string().nullable(),
publicIpv6: z.string().nullable(),
warp: z.enum(['on', 'off', 'unknown']),
colo: z.string().nullable(),
ipv4: WarpTraceSchema.nullable(),
ipv6: WarpTraceSchema.nullable(),
operation: WarpOperationSchema,
lastError: z.string().nullable(),
});

export const NodeSystemInfoSchema = z.object({
arch: z.string(),
cpus: z.number().int(),
Expand All @@ -27,6 +74,8 @@ export const NodeSystemStatsSchema = z.object({
uptime: z.number(),
loadAvg: z.array(z.number()),
interface: z.nullable(NetworkInterfaceSchema),
host: z.optional(HostConnectivitySchema),
warp: z.optional(WarpStatusSchema),
});

export type TNodeSystemStats = z.infer<typeof NodeSystemStatsSchema>;
Expand All @@ -39,3 +88,6 @@ export const NodeSystemSchema = z.object({
export type TNetworkInterface = z.infer<typeof NetworkInterfaceSchema>;
export type TNodeSystemInfo = z.infer<typeof NodeSystemInfoSchema>;
export type TNodeSystem = z.infer<typeof NodeSystemSchema>;
export type TWarpStatus = z.infer<typeof WarpStatusSchema>;
export type THostConnectivity = z.infer<typeof HostConnectivitySchema>;
export type TWarpOperation = z.infer<typeof WarpOperationSchema>;
3 changes: 2 additions & 1 deletion src/modules/remnawave-node.modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { HandlerModule } from './handler/handler.module';
import { PluginModule } from './_plugin/plugin.module';
import { XrayModule } from './xray-core/xray.module';
import { StatsModule } from './stats/stats.module';
import { WarpModule } from './warp/warp.module';

@Module({
imports: [NetworkStatsModule, PluginModule, StatsModule, XrayModule, HandlerModule],
imports: [NetworkStatsModule, PluginModule, WarpModule, StatsModule, XrayModule, HandlerModule],
providers: [],
})
export class RemnawaveNodeModules implements OnApplicationShutdown {
Expand Down
3 changes: 2 additions & 1 deletion src/modules/stats/stats.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { CqrsModule } from '@nestjs/cqrs';
import { Module } from '@nestjs/common';

import { StatsController } from './stats.controller';
import { WarpModule } from '../warp/warp.module';
import { StatsService } from './stats.service';
@Module({
imports: [CqrsModule],
imports: [CqrsModule, WarpModule],
providers: [StatsService],
controllers: [StatsController],
})
Expand Down
10 changes: 9 additions & 1 deletion src/modules/stats/stats.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ import {
import { GetInterfaceStatsQuery } from '../network-stats/queries/get-interface-stats/get-interface-stats.query';
import { GetTorrentBlockerReportsCountQuery } from '../_plugin/queries/get-torrent-blocker-reports-count';
import { IGetUserOnlineStatusRequest } from './interfaces';
import { WarpService } from '../warp/warp.service';

@Injectable()
export class StatsService {
constructor(
@InjectXtls() private readonly xtlsSdk: XtlsApi,
private readonly queryBus: QueryBus,
private readonly warpService: WarpService,
) {}
private readonly logger = new Logger(StatsService.name);

Expand Down Expand Up @@ -72,7 +74,11 @@ export class StatsService {
};
}

const interfaceStats = await this.queryBus.execute(new GetInterfaceStatsQuery());
const [interfaceStats, warpStatus, hostConnectivity] = await Promise.all([
this.queryBus.execute(new GetInterfaceStatsQuery()),
this.warpService.getStatus(),
this.warpService.getHostConnectivity(),
]);
const systemStats = getSystemStats();
const reportsCount = await this.queryBus.execute(
new GetTorrentBlockerReportsCountQuery(),
Expand All @@ -90,6 +96,8 @@ export class StatsService {
{
...systemStats,
interface: interfaceStats,
host: hostConnectivity,
warp: warpStatus,
},
),
};
Expand Down
56 changes: 56 additions & 0 deletions src/modules/warp/warp.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Controller, Get, Post, UseFilters, UseGuards } from '@nestjs/common';

import { JwtDefaultGuard } from '@common/guards/jwt-guards';
import { HttpExceptionFilter } from '@common/exception';
import {
DisableWarpCommand,
EnableWarpCommand,
GetWarpStatusCommand,
InstallWarpCommand,
UninstallWarpCommand,
} from '@libs/contracts/commands';
import { WARP_CONTROLLER, WARP_ROUTES } from '@libs/contracts/api';

import { WarpService } from './warp.service';

@UseFilters(HttpExceptionFilter)
@UseGuards(JwtDefaultGuard)
@Controller(WARP_CONTROLLER)
export class WarpController {
constructor(private readonly warpService: WarpService) {}

@Get(WARP_ROUTES.STATUS)
public async status(): Promise<GetWarpStatusCommand.Response> {
return {
response: await this.warpService.getStatus(),
};
}

@Post(WARP_ROUTES.ENABLE)
public async enable(): Promise<EnableWarpCommand.Response> {
return {
response: await this.warpService.enable(),
};
}

@Post(WARP_ROUTES.INSTALL)
public async install(): Promise<InstallWarpCommand.Response> {
return {
response: await this.warpService.install(),
};
}

@Post(WARP_ROUTES.DISABLE)
public async disable(): Promise<DisableWarpCommand.Response> {
return {
response: await this.warpService.disable(),
};
}

@Post(WARP_ROUTES.UNINSTALL)
public async uninstall(): Promise<UninstallWarpCommand.Response> {
return {
response: await this.warpService.uninstall(),
};
}
}
11 changes: 11 additions & 0 deletions src/modules/warp/warp.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';

import { WarpController } from './warp.controller';
import { WarpService } from './warp.service';

@Module({
controllers: [WarpController],
providers: [WarpService],
exports: [WarpService],
})
export class WarpModule {}
Loading