Browse Source

major refactor to typescript

develop
ray-1337 2 years ago
parent
commit
877f54ad00
No known key found for this signature in database GPG Key ID: DED41DCC150FCD32
  1. 37
      index.d.ts
  2. 1
      index.js
  3. 27
      src/Index.ts
  4. 31
      src/Main.js
  5. 37
      src/Typings.d.ts
  6. 105
      src/Util.js
  7. 40
      src/Util.ts
  8. 74
      src/methods/Allow.ts
  9. 29
      src/methods/Delete.ts
  10. 76
      src/methods/Deny.ts
  11. 10
      src/methods/Disable.ts
  12. 13
      src/methods/Enable.ts
  13. 23
      src/methods/Logging.ts
  14. 22
      src/methods/Reload.ts
  15. 22
      src/methods/Reset.ts
  16. 45
      src/methods/Status.ts
  17. 92
      src/methods/allow.js
  18. 30
      src/methods/delete.js
  19. 92
      src/methods/deny.js
  20. 36
      src/methods/logging.js
  21. 24
      src/methods/reload.js
  22. 24
      src/methods/reset.js
  23. 51
      src/methods/status.js
  24. 26
      tsconfig.json

37
index.d.ts

@ -1,37 +0,0 @@
declare const nodeUfw: {
name: string;
version: string;
disable: () => Promise<Boolean>;
enable: () => Promise<Boolean>;
reset: () => Promise<Boolean>;
reload: () => Promise<Boolean>;
status: (raw?: boolean) => Promise<string | Array<ParsedStatus>>;
logging: (type: LoggingType) => Promise<Boolean>;
allow: {
port: (port: number, protocol?: "udp" | "tcp") => Promise<Boolean>;
address: (address: string, port?: number, protocol?: "udp" | "tcp") => Promise<Boolean>;
};
deny: {
port: (port: number, protocol?: "udp" | "tcp") => Promise<Boolean>;
address: (address: string, port?: number, protocol?: "udp" | "tcp") => Promise<Boolean>;
};
};
type LoggingType = 'off' | 'on' | 'low' | 'medium' | 'high' | 'full';
interface ParsedStatus {
to: string;
action: string;
from: string;
}
export = nodeUfw;

1
index.js

@ -1 +0,0 @@
module.exports = require("./src/Main.js");

27
src/Index.ts

@ -0,0 +1,27 @@
import { checkSudo, checkNodeVersion, checkPlatform, checkPlatformExact } from './Util';
if (!checkSudo()) {
throw new Error("You need to be root to run this package.");
};
if (!checkNodeVersion()) {
throw new Error(`The Node version must be at least v14 or above.`);
};
if (!checkPlatform()) {
throw new Error("Your platform must be at least `linux`.");
};
if (!checkPlatformExact()) {
throw new Error("node-ufw only supported on Ubuntu.");
};
export { default as allow } from "./methods/Allow";
export { default as deny } from "./methods/Deny";
export { default as disable } from "./methods/Disable";
export { default as enable } from "./methods/Enable";
export { default as status } from "./methods/Status";
export { default as delete } from "./methods/Delete";
export { default as reset } from "./methods/Reset";
export { default as reload } from "./methods/Reload";
export { default as logging } from "./methods/Logging"

31
src/Main.js

@ -1,31 +0,0 @@
const {checkSudo, checkNodeVersion, checkPlatform, checkPlatformExact} = require('./Util');
if (!checkSudo()) {
throw new Error("You need to be root to run this package.");
};
if (!checkNodeVersion()) {
throw new Error(`The Node version must be at least v14 or above.`);
};
if (!checkPlatform()) {
throw new Error("Your platform must be at least `linux`.");
};
if (!checkPlatformExact()) {
throw new Error("node-ufw only supported on Ubuntu.");
};
module.exports = {
name: require("../package.json").name,
version: require("../package.json").version,
allow: require("./methods/allow"),
deny: require("./methods/deny"),
disable: require("./methods/disable"),
enable: require("./methods/enable"),
status: require("./methods/status"),
delete: require("./methods/delete"),
reset: require("./methods/reset"),
reload: require("./methods/reload"),
logging: require("./methods/logging")
};

37
src/Typings.d.ts

@ -0,0 +1,37 @@
interface ParsedStatus {
to: string;
action: string;
from: string;
}
type LoggingType = 'off' | 'on' | 'low' | 'medium' | 'high' | 'full';
type PortProtocol = "udp" | "tcp";
export declare const nodeUfw: {
name: string;
version: string;
disable: () => Promise<Boolean>;
enable: () => Promise<Boolean>;
reset: () => Promise<Boolean>;
reload: () => Promise<Boolean>;
status: (raw?: boolean) => Promise<string | ParsedStatus[] | null>;
logging: (type: LoggingType) => Promise<Boolean>;
allow: {
port: (port: number, protocol?: PortProtocol) => Promise<Boolean>;
address: (address: string, port?: number, protocol?: PortProtocol) => Promise<Boolean>;
};
deny: {
port: (port: number, protocol?: PortProtocol) => Promise<Boolean>;
address: (address: string, port?: number, protocol?: PortProtocol) => Promise<Boolean>;
};
};

105
src/Util.js

@ -1,105 +0,0 @@
const {execSync} = require("child_process");
// const {promisify} = require("util");
// const promisifiedExec = promisify(exec);
const {getuid, versions, platform} = require("process");
module.exports.checkSudo = function () {
return getuid && getuid() == 0 ? true : false;
};
module.exports.checkNodeVersion = function () {
const currentApropriateVersion = 14, nodeVersion = versions.node.split('.');
return +nodeVersion[0] > currentApropriateVersion ? true : false;
};
module.exports.checkPlatform = function () {
// https://nodejs.org/api/process.html#process_process_platform
return platform == "linux" ? true : false;
};
// module.exports.getDistroInfo = async function () {
// let current = {
// distributorID: null, distributorVersion: null
// };
// try {
// // check version
// let {stdout, stderr} = await promisifiedExec('lsb_release -i -r');
// if (stderr) {
// throw new Error(`Error while checking Linux distribution information: ${stderr}`);
// };
// if (stdout) {
// // sanitize
// let parsed = stdout
// .split(/\r|\n/gi) // remove break lines
// .map(x => x.replace(/\s/gi, "")) // remove spaces, only remains [e.g. DistributorID:Ubuntu]
// .filter(x => x); // filter empty string
// let findDistributorID = parsed.find(val => val.match(/^(DistributorID)/gi));
// let findReleaseVersion = parsed.find(val => val.match(/^(Release)/gi));
// if (findDistributorID) {
// let splitViaColon = findDistributorID.split(/(:)/gi);
// if (splitViaColon) current.distributorID = splitViaColon.pop().toLowerCase();
// };
// if (findReleaseVersion) {
// let splitViaColon = findReleaseVersion.split(/(:)/gi);
// if (splitViaColon) current.distributorVersion = splitViaColon.pop().toLowerCase();
// };
// };
// } catch {};
// return current;
// };
module.exports.checkPlatformExact = function () {
// let distroInfo = await this.getDistroInfo();
// if (!distroInfo?.distributorID || !distroInfo?.distributorVersion) {
// throw new Error("Missing distro platform information.");
// };
// // https://en.wikipedia.org/wiki/Uncomplicated_Firewall
// let platform = distroInfo.distributorID;
// if (String(platform).toLowerCase() !== "ubuntu") {
// throw new Error("node-ufw only supported on Ubuntu.");
// };
// return true;
try {
const check = execSync("cat /etc/*release | grep -E ^NAME");
return check?.toString("utf-8").match("Ubuntu") ? true : false;
} catch (e) {
console.error(e);
return false;
};
};
module.exports.checkAppropriatePort = function(port) {
const portLimit = Math.round(2 ** 16 - 1);
if (typeof port !== "number") throw new Error("The port must be type of number.");
return (port > 0 || port <= portLimit) ? true : false;
};
module.exports.checkAppropriateIP = function(address) {
if (typeof address !== "string") throw new Error("The address must be type of string.");
// https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
// also support subnet/net mask
let regex = new RegExp(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))?$/gi);
return address.match(regex) !== null ? true : false;
};
// soon to be continued
// module.exports.checkPlatformVersion = function () {
// let distroInfo = this.getDistroInfo();
// if (!distroInfo?.distributorID || !distroInfo?.distributorVersion) {
// throw new Error("Missing distro platform information.");
// };
// };

40
src/Util.ts

@ -0,0 +1,40 @@
import { execSync } from "node:child_process";
import { getuid, versions, platform } from "node:process";
export function checkSudo() {
return getuid && getuid() == 0 ? true : false;
};
export function checkNodeVersion() {
const currentApropriateVersion = 14, nodeVersion = versions.node.split('.');
return +nodeVersion[0] > currentApropriateVersion ? true : false;
};
export function checkPlatform() {
// https://nodejs.org/api/process.html#process_process_platform
return platform == "linux" ? true : false;
};
export function checkPlatformExact() {
try {
const check = execSync("cat /etc/*release | grep -E ^NAME");
return check?.toString("utf-8").match("Ubuntu") ? true : false;
} catch (e) {
console.error(e);
return false;
};
};
export function checkAppropriatePort(port: number) {
const portLimit = Math.round(2 ** 16 - 1);
return port > 0 || port <= portLimit;
};
export function checkAppropriateIP(address: string) {
// https://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
let regex = new RegExp(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))?$/gi);
return address.match(regex) !== null ? true : false;
};

74
src/methods/Allow.ts

@ -0,0 +1,74 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
import { checkAppropriatePort, checkAppropriateIP } from "../Util";
import type { PortProtocol } from "../Typings";
const promisifiedExec = promisify(exec);
/**
* Allow incoming requests through specific port. (root/sudo access is mandatory)
*/
async function port(port: number, protocol?: PortProtocol) {
try {
// check port range
let checkPort = checkAppropriatePort(port);
if (!checkPort) return false;
let res = await promisifiedExec(`echo "y" | sudo ufw allow ${port}${protocol ? `/${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw err;
};
}
/**
* Allow incoming requests through specific (IP) address. (root/sudo access is mandatory)
*/
async function address(address: string, port: number, protocol?: PortProtocol) {
try {
// address validation
let checkAddress = checkAppropriateIP(address);
if (!checkAddress) return false;
// port validation
if (port) {
let checkPort = checkAppropriatePort(port);
if (!checkPort) return false;
};
let res = await promisifiedExec(`echo "y" | sudo ufw allow from ${address} ${port ? `to any port ${port}` : ""} ${protocol ? `proto ${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw err;
};
}
export default {
address, port
};

29
src/methods/Delete.ts

@ -0,0 +1,29 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
const promisifiedExec = promisify(exec);
/**
* Delete ufw rule(s). (root/sudo access is mandatory)
*/
export default async function(num: number) {
try {
if (num === 0) {
num = 1;
};
let res = await promisifiedExec(`echo "y" | sudo ufw delete ${num}`);
if (res.stderr) {
throw new Error(res.stderr);
};
if (res.stdout) {
return true;
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw err;
};
};

76
src/methods/Deny.ts

@ -0,0 +1,76 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
import { checkAppropriatePort, checkAppropriateIP } from "../Util";
import type { PortProtocol } from "../Typings";
const promisifiedExec = promisify(exec);
/**
* Deny incoming requests through specific port. (root/sudo access is mandatory)
*/
async function port(port: number, protocol?: PortProtocol) {
try {
// check port range
let checkPort = checkAppropriatePort(port);
if (!checkPort) return false;
let res = await promisifiedExec(`echo "y" | sudo ufw deny ${port}${protocol ? `/${protocol}` : ""}`);
if (res.stderr) {
throw new Error(res.stderr);
};
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw err;
};
};
/**
* Deny incoming requests through specific (IP) address. (root/sudo access is mandatory)
*/
async function address(address: string, port: number, protocol?: PortProtocol) {
try {
// address validation
let checkAddress = checkAppropriateIP(address);
if (!checkAddress) return false;
// port validation
if (port) {
let checkPort = checkAppropriatePort(port);
if (!checkPort) return false;
};
let res = await promisifiedExec(`echo "y" | sudo ufw deny from ${address} ${port ? `to any port ${port}` : ""} ${protocol ? `proto ${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw err;
};
};
export default {
address, port
};

10
src/methods/disable.js → src/methods/Disable.ts

@ -1,13 +1,11 @@
const {exec} = require("child_process");
const {promisify} = require("util");
import { exec } from "node:child_process";
import { promisify } from "node:util";
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Disable ufw. (root/sudo access is mandatory)
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports = async function() {
export default async function() {
try {
let res = await promisifiedExec(`echo "y" | sudo ufw disable`);
@ -19,6 +17,6 @@ module.exports = async function() {
return false;
};
} catch (err) {
throw new Error(err);
throw err;
};
};

13
src/methods/enable.js → src/methods/Enable.ts

@ -1,13 +1,8 @@
const {exec} = require("child_process");
const {promisify} = require("util");
import { exec } from "node:child_process";
import { promisify } from "node:util";
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Enable ufw. (root/sudo access is mandatory)
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports = async function() {
export default async function() {
try {
// https://serverfault.com/a/790150
let res = await promisifiedExec(`echo "y" | sudo ufw enable`);
@ -20,6 +15,6 @@ module.exports = async function() {
return false;
};
} catch (err) {
throw new Error(err);
throw err;
};
};

23
src/methods/Logging.ts

@ -0,0 +1,23 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
import type { LoggingType } from "../Typings";
const promisifiedExec = promisify(exec);
/**
* Set/toggle UFW logging. (root/sudo access is mandatory)
*/
export default async function(type: LoggingType) {
try {
let res = await promisifiedExec(`sudo ufw logging ${type}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
return false;
};
} catch (err) {
throw err;
};
};

22
src/methods/Reload.ts

@ -0,0 +1,22 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
const promisifiedExec = promisify(exec);
/**
* Reloads firewall. (root/sudo access is mandatory)
*/
export default async function() {
try {
let res = await promisifiedExec("sudo ufw reload");
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
return false;
};
} catch (err) {
throw err;
};
};

22
src/methods/Reset.ts

@ -0,0 +1,22 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
const promisifiedExec = promisify(exec);
/**
* Disables and resets firewall to installation defaults. No prompt. Use this wisely. (root/sudo access is mandatory)=
*/
export default async function() {
try {
let res = await promisifiedExec("sudo ufw --force reset");
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
return false;
};
} catch (err) {
throw err;
};
};

45
src/methods/Status.ts

@ -0,0 +1,45 @@
import { exec } from "node:child_process";
import { promisify } from "node:util";
import type { ParsedStatus } from "../Typings";
const promisifiedExec = promisify(exec);
/**
* List of currently activated ufw. (root/sudo access is mandatory)
*/
export default async function(raw?: boolean): Promise<string | ParsedStatus[] | null> {
try {
let res = await promisifiedExec("sudo ufw status");
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
if (raw) return res.stdout;
let list = [];
// parsing
let parsedStatus = res.stdout.replace(/\r|\n/gi, " ").split(/\s{2,}/gi).filter(x => x.length);
if (!parsedStatus.length) return [];
let findAfterFrom = parsedStatus.findIndex(x => x == "----");
let afterSlice = parsedStatus.slice(findAfterFrom + 1, parsedStatus.length);
if (!afterSlice.length) return [];
for (let i = 0; i < afterSlice.length; i++) {
if (i % 3 == 0) {
let to = afterSlice[i];
let action = afterSlice[i + 1];
let from = afterSlice[i + 2];
list.push({to, action, from});
};
};
return list;
};
return null;
} catch (err) {
throw err;
};
};

92
src/methods/allow.js

@ -1,92 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Allow incoming requests through specific port. (root/sudo access is mandatory)
* @param {number} port The connection pange. From range 1 - 65535.
* @param {"udp" | "tcp" | undefined} protocol The protocol.
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports.port = async function (port, protocol) {
try {
if (!port) throw new Error("Missing port input.");
if (typeof port !== "number") throw new Error("The port must be type of number.");
// check port range
let checkPort = util.checkAppropriatePort(port);
if (!checkPort) return false;
if (protocol) {
if (typeof protocol !== "string") throw new Error("The protocol must be type of string.");
if (protocol !== "tcp" || protocol !== "udp") throw new Error('The protocol must be either "tcp" or "udp"');
};
let res = await promisifiedExec(`echo "y" | sudo ufw allow ${port}${protocol ? `/${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw new Error(err);
};
};
/**
* Allow incoming requests through specific (IP) address. (root/sudo access is mandatory)
* @param {string} address IP address, supported by subnet/net mask. From range 0.0.0.0 to 255.255.255.255
* @param {number | undefined} port The connection pange. From range 1 - 65535.
* @param {"udp" | "tcp" | undefined} protocol The protocol.
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports.address = async function (address, port, protocol) {
try {
// address validation
if (!address) throw new Error("Missing address input.");
if (typeof address !== "string") throw new Error("The address must be type of string.");
let checkAddress = util.checkAppropriateIP(address);
if (!checkAddress) return false;
// port validation
if (port) {
if (typeof port !== "number") throw new Error("The port must be type of number.");
let checkPort = util.checkAppropriatePort(port);
if (!checkPort) return false;
};
// protocol (tcp/udp) validation
if (protocol) {
if (typeof protocol !== "string") throw new Error("The protocol must be type of string.");
if (protocol !== "tcp" || protocol !== "udp") throw new Error('The protocol must be either "tcp" or "udp"');
};
let res = await promisifiedExec(`echo "y" | sudo ufw allow from ${address} ${port ? `to any port ${port}` : ""} ${protocol ? `proto ${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw new Error(err);
};
};

30
src/methods/delete.js

@ -1,30 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Delete ufw rule(s). (root/sudo access is mandatory)
* @param {number} num Number of the rules list. The first rule starts from number 1.
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports = async function(num) {
try {
if (!num) throw new Error("Missing num input.");
if (typeof num !== "number") throw new Error("The num must be type of number.");
if (num === 0) num = 1;
let res = await promisifiedExec(`echo "y" | sudo ufw delete ${num}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw new Error(err);
};
};

92
src/methods/deny.js

@ -1,92 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Deny incoming requests through specific port. (root/sudo access is mandatory)
* @param {number} port The connection pange. From range 1 - 65535.
* @param {"udp" | "tcp" | undefined} protocol The protocol.
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports.port = async function (port, protocol) {
try {
if (!port) throw new Error("Missing port input.");
if (typeof port !== "number") throw new Error("The port must be type of number.");
// check port range
let checkPort = util.checkAppropriatePort(port);
if (!checkPort) return false;
if (protocol) {
if (typeof protocol !== "string") throw new Error("The protocol must be type of string.");
if (protocol !== "tcp" || protocol !== "udp") throw new Error('The protocol must be either "tcp" or "udp"');
};
let res = await promisifiedExec(`echo "y" | sudo ufw deny ${port}${protocol ? `/${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw new Error(err);
};
};
/**
* Deny incoming requests through specific (IP) address. (root/sudo access is mandatory)
* @param {string} address IP address, supported by subnet/net mask. From range 0.0.0.0 to 255.255.255.255
* @param {number | undefined} port The connection pange. From range 1 - 65535.
* @param {"udp" | "tcp" | undefined} protocol The protocol.
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports.address = async function (address, port, protocol) {
try {
// address validation
if (!address) throw new Error("Missing address input.");
if (typeof address !== "string") throw new Error("The address must be type of string.");
let checkAddress = util.checkAppropriateIP(address);
if (!checkAddress) return false;
// port validation
if (port) {
if (typeof port !== "number") throw new Error("The port must be type of number.");
let checkPort = util.checkAppropriatePort(port);
if (!checkPort) return false;
};
// protocol (tcp/udp) validation
if (protocol) {
if (typeof protocol !== "string") throw new Error("The protocol must be type of string.");
if (protocol !== "tcp" || protocol !== "udp") throw new Error('The protocol must be either "tcp" or "udp"');
};
let res = await promisifiedExec(`echo "y" | sudo ufw deny from ${address} ${port ? `to any port ${port}` : ""} ${protocol ? `proto ${protocol}` : ""}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
// will find a better way to parse this
if (res.stdout.toLowerCase().match(/(added)/gi)) {
return true;
} else {
console.log(res.stdout);
return false;
};
} else {
console.log(res.stdout);
return false;
};
} catch (err) {
throw new Error(err);
};
};

36
src/methods/logging.js

@ -1,36 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Set/toggle UFW logging. (root/sudo access is mandatory)
* @param {'off' | 'on' | 'low' | 'medium' | 'high' | 'full'} type A type of UFWlogging.
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports = async function(type) {
try {
if (!type) throw new Error("Missing type input.");
if (typeof type !== "string") throw new Error("The type must be type of string.");
type = type.toLowerCase();
// https://manpages.ubuntu.com/manpages/focal/en/man8/ufw.8.html#logging
let appropriateType = ['off', 'on', 'low', 'medium', 'high', 'full'];
if (!appropriateType.includes(type)) {
throw new Error(`Invalid type. Currently supported: ${appropriateType.join(", ")}`);
};
let res = await promisifiedExec(`sudo ufw logging ${type}`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
return false;
};
} catch (err) {
throw new Error(err);
};
};

24
src/methods/reload.js

@ -1,24 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Reloads firewall. (root/sudo access is mandatory)
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports = async function() {
try {
let res = await promisifiedExec(`sudo ufw reload`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
return false;
};
} catch (err) {
throw new Error(err);
};
};

24
src/methods/reset.js

@ -1,24 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* Disables and resets firewall to installation defaults. No prompt. Use this wisely. (root/sudo access is mandatory)
* @returns {Promise<Boolean>} Returns a boolean.
*/
module.exports = async function() {
try {
let res = await promisifiedExec(`sudo ufw --force reset`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
return true;
} else {
return false;
};
} catch (err) {
throw new Error(err);
};
};

51
src/methods/status.js

@ -1,51 +0,0 @@
const {exec} = require("child_process");
const {promisify} = require("util");
const promisifiedExec = promisify(exec);
const util = require("../Util");
/**
* List of currently activated ufw. (root/sudo access is mandatory)
* @param {boolean} [raw=false] A raw version of "ufw status"
* @returns {Promise<string | {to: string, action: string, from: string}[]>} Returns a string if "raw" param is included, otherwise a list of array with to/action/from.
*/
module.exports = async function(raw) {
if (raw && typeof raw !== "boolean") {
throw new Error("The raw must be type of boolean.");
};
try {
let res = await promisifiedExec(`sudo ufw status`);
if (res.stderr) throw new Error(res.stderr);
if (res.stdout) {
if (!raw) {
let list = [];
// parsing
let parsedStatus = res.stdout.replace(/\r|\n/gi, " ").split(/\s{2,}/gi).filter(x => x.length);
if (!parsedStatus.length) return [];
let findAfterFrom = parsedStatus.findIndex(x => x == "----");
let afterSlice = parsedStatus.slice(findAfterFrom + 1, parsedStatus.length);
if (!afterSlice.length) return [];
for (let i = 0; i < afterSlice.length; i++) {
if (i % 3 == 0) {
let to = afterSlice[i];
let action = afterSlice[i + 1];
let from = afterSlice[i + 2];
list.push({to, action, from});
};
};
return list;
} else {
return res.stdout;
};
};
} catch (err) {
throw new Error(err);
};
};

26
tsconfig.json

@ -0,0 +1,26 @@
{
"compilerOptions": {
"outDir": "dist",
"module": "CommonJS",
"target": "ESNext",
"inlineSourceMap": true,
"importHelpers": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": false,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"allowUnusedLabels": false,
"allowUnreachableCode": false,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"declaration": true,
"noEmitOnError": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts"],
"exclude": ["node_modules", "dist", "test"]
}
Loading…
Cancel
Save