24 changed files with 429 additions and 538 deletions
@ -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 +0,0 @@ |
|||
module.exports = require("./src/Main.js"); |
@ -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" |
@ -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") |
|||
}; |
@ -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>; |
|||
}; |
|||
}; |
@ -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.");
|
|||
// };
|
|||
// };
|
@ -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; |
|||
}; |
@ -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 |
|||
}; |
@ -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; |
|||
}; |
|||
}; |
@ -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 |
|||
}; |
@ -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; |
|||
}; |
|||
}; |
@ -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; |
|||
}; |
|||
}; |
@ -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; |
|||
}; |
|||
}; |
@ -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; |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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); |
|||
}; |
|||
}; |
@ -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…
Reference in new issue