Skip to content

Commit

Permalink
✨ Reconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinbreiz committed Mar 21, 2024
1 parent e66e397 commit 0813481
Show file tree
Hide file tree
Showing 5 changed files with 398 additions and 430 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ FROM node:18.16.0

RUN apt-get update && apt-get install -y netcat-openbsd && rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh

WORKDIR /app

COPY . .
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ FROM node:18.16.0

RUN apt-get update && apt-get install -y netcat-openbsd && rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh

WORKDIR /app

COPY ./package.json ./
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"class-validator": "^0.14.0",
"dayjs": "^1.11.9",
"dockerode": "^3.3.5",
"js-yaml": "^4.1.0",
"mongoose": "^7.5.0",
"nodemailer": "^6.9.5",
"passport": "^0.6.0",
Expand All @@ -50,7 +51,8 @@
"@types/bcrypt": "^5.0.0",
"@types/dockerode": "^3.3.19",
"@types/express": "^4.17.17",
"@types/node": "20.5.7",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.11.30",
"@types/passport-jwt": "^3.0.9",
"@types/passport-local": "^1.0.35",
"@typescript-eslint/eslint-plugin": "^6.5.0",
Expand Down
147 changes: 92 additions & 55 deletions src/reconfig/reconfig.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,70 +3,107 @@ import { Subject } from 'rxjs';
import { ReConfigDto } from './_utils/dto/request/reconfig-request.dto';
import * as Docker from 'dockerode';
import { RpcException } from '@nestjs/microservices';
import { Container, Exec } from 'dockerode';
import { promises as fs } from 'fs';
import * as yaml from 'js-yaml';
import { exec } from 'child_process';
var DockerodeCompose = require('dockerode-compose')

interface dummies {
num_services: number;
ip_addresses: Array<string>;
}
@Injectable()
export class ReconfigureService {

interface ftps {
ip_address: string;
port: string;
}
private docker = new Docker();

interface NewConfig {
dummy_pc: dummies;
ftp: ftps;
}
private configPath = '/app/honeypot/generator/config.json';

function delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
public async reconfigHoneypot(Reconfig: ReConfigDto) {
//check config
if (!Reconfig.config) throw new RpcException('Config cannot be empty')

@Injectable()
export class ReconfigureService {
await this.saveConfig(Reconfig.config);

private docker = new Docker();
//recup liste dockers
const containers = await this.docker.listContainers({ all: true });
const buildContainers = containers.filter((container) => container.Names[0].startsWith('/honeypot_'));

/*private validate_config(configJson: NewConfig) {
if (configJson.dummy_pc.num_services = 0)
return
}*/

public async reconfigHoneypot(Reconfig: ReConfigDto) {
//check config
if (!Reconfig.config) throw new RpcException('Config cannot be empty')

//recup liste dockers
const containers = await this.docker.listContainers({ all: true });
const buildContainers = containers.filter((container) => container.Names[0].startsWith('/honeypot_'));

buildContainers.forEach(element => {
this.docker.getContainer(element.Id).stop().catch((e) => console.log(e));
});

//creer docker depuis config
let configJson: NewConfig = JSON.parse(Reconfig.config);

//this.validate_config(configJson);
await delay(1000)
var newDocker = new Docker()
//newDocker.createContainer({Image: 'ubuntu', Cmd: ['/bin/bash'], name: 'honeypot_dummy_pc_123'}, function(err, container){container?.start({})})
for (let i=0; i < configJson.dummy_pc.num_services; i++) {
newDocker.run('ubuntu', ['bash', '-c', 'sleep infinity'], process.stdout, {Hostname: configJson.dummy_pc.ip_addresses[i], name:'honeypot_dummy_pc_'+i},function() {
console.log("running new dummy pc on " + configJson.dummy_pc.ip_addresses[i]);
});
await Promise.all(buildContainers.map(async element => {
const container = await this.docker.getContainer(element.Id);
await container.stop().catch((e) => console.log(e));
await container.remove({force: true}).catch((e) => console.log(e));
}));

const generatorContainerInfo = containers.find((container) => container.Names.some(name => name.startsWith('/generator')));
if (!generatorContainerInfo) {
throw new Error('Generator container not found');
}

const generatorContainer = await this.docker.getContainer(generatorContainerInfo.Id);
await this.executeInContainer(generatorContainer, ["python3", "/generator.py"]);

await this.startHoneypotServices("/app/honeypot/generator/docker-compose.yml");

console.log('Reconfiguration completed successfully.');
}
if (configJson.ftp.ip_address != "") {
newDocker.run('ubuntu', ['bash', '-c', 'sleep infinity'], process.stdout, {Hostname: configJson.ftp.ip_address, name:'honeypot_dummy_ftp_1 '},function() {
console.log("running new dummy ftp on " + configJson.ftp.ip_address + " on port " + configJson.ftp.port);
})

private async saveConfig(config: string): Promise<void> {
await fs.writeFile(this.configPath, config, 'utf-8');
}

const generator = containers.filter((container)=> container.Names[0].startsWith('/generator'))
console.log(generator)
this.docker.getContainer(generator[0].Id).exec({Cmd: ['python3', 'generator.py'], AttachStdin: true, AttachStdout: true})

private async executeInContainer(container: Container, command: string[]): Promise<void> {
const exec: Exec = await container.exec({
Cmd: command,
AttachStdin: false,
AttachStdout: true,
AttachStderr: true,
Tty: false,
});

const stream = await exec.start({ Detach: false, Tty: false });

container.modem.demuxStream(stream, process.stdout, process.stderr);

return new Promise((resolve, reject) => {
stream.on('end', resolve);
stream.on('error', reject);
stream.resume();
});
}

private async startHoneypotServices(composeFilePath: string): Promise<void> {
try {
// Lecture du fichier docker-compose.yml
const fileContents = await fs.readFile(composeFilePath, 'utf8');
const composeObject = yaml.load(fileContents) as any;
const services = composeObject.services;

// Filtrage des services dont le conteneur commence par "honeypot_"
const honeypotServices = Object.keys(services).filter(serviceName => {
const containerName = services[serviceName].container_name;
return containerName && containerName.startsWith('honeypot_');
});

if (honeypotServices.length === 0) {
console.log("No honeypot services found to start.");
return;
}

console.log(honeypotServices);

// Construction de la commande pour démarrer uniquement les services filtrés
const command = `docker compose -f ${composeFilePath} up --force-recreate -d ${honeypotServices.join(' ')}`;

// Exécution de la commande
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});

} catch (e) {
console.error(e);
}
}
}
Loading

0 comments on commit 0813481

Please sign in to comment.