Skip to content

Commit

Permalink
WIP cli tool for firewall
Browse files Browse the repository at this point in the history
  • Loading branch information
imgurbot12 committed Sep 14, 2017
1 parent 359135b commit b9478fb
Show file tree
Hide file tree
Showing 8 changed files with 745 additions and 0 deletions.
62 changes: 62 additions & 0 deletions cli/blacklist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package cli

import (
"fmt"

cli "gopkg.in/urfave/cli.v1"
)

/***Variables***/

type blacklistRecord struct {
IPAddress string
LastSeen string
EntryDate string
}

/***Functions***/

//blacklistAppend : append given ip-address to blackist
func blacklistAppend(c *cli.Context) {
// get variables
ip := getIPWithDuplicate(c, "blacklist")
reason := c.String("reason")
if reason == "" {
cliError(c, "Flag: \"reason\" must not be blank!")
}
// run append
if _, err := db.Exec("INSERT INTO blacklist VALUES(?,datetime('now'),datetime('now'),?,0);", ip, reason); err != nil {
cliError(c, fmt.Sprintf("SQL-ERROR: %s", err.Error()))
}
fmt.Println("Entry added to blacklist")
}

//blacklistRemove : remove given ip-address from blacklist
func blacklistRemove(c *cli.Context) {
ip := getIP(c, "ipaddress")
// run delete
if _, err := db.Exec("DELETE FROM blacklist WHERE IPAddress=?;", ip); err != nil {
cliError(c, fmt.Sprintf("SQL-ERROR: %s", err.Error()))
}
fmt.Println("Entry removed from blacklist")
}

//blacklistDisplay: display all ip-addresses in blacklist
func blacklistDisplay(c *cli.Context) {
rows, err := db.Query("SELECT IPAddress,LastSeen,EntryDate FROM blacklist WHERE LogicalDelete=0")
if err != nil {
cliError(c, fmt.Sprintf("SQL-ERROR: %s", err.Error()))
}
var counter int
var rec *blacklistRecord
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
fmt.Println(" # | IP-Address | LastSeen | EntryDate ")
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
for rows.Next() {
rec = new(blacklistRecord)
rows.Scan(&rec.IPAddress, &rec.LastSeen, &rec.EntryDate)
fmt.Printf(" %-5d | %-15s | %-15s | %s \n", counter, rec.IPAddress, rec.LastSeen, rec.EntryDate)
counter++
}
rows.Close()
}
203 changes: 203 additions & 0 deletions cli/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package cli

import (
"fmt"
"net"
"os"

cli "gopkg.in/urfave/cli.v1"
)

//TODO: disallow whitelist/blacklist to use ip-ranges as that is what rules are for +bug
//TODO: add indexing for rules? +enhancement

/***Varaiables***/

var listAppendRules = []cli.Flag{
cli.StringFlag{
Name: "ipaddress, ip",
Usage: "the ip-address you want to whitelist",
},
cli.StringFlag{
Name: "reason, r",
Usage: "the reason they are whitelisted",
},
}
var listRemoveRules = []cli.Flag{
listAppendRules[0],
}

var commands = cli.Commands{
//rule commands
{
Name: "rules",
Aliases: []string{"r"},
Usage: "modify firewall rules",
Action: rulesDisplay,
Subcommands: cli.Commands{
// append new rule to end of rule chain
{
Name: "append",
Usage: "append a rule to the end of the rule chain",
Aliases: []string{"app"},
Action: rulesAppend,
Flags: rulesAppendArgs,
},
// insert new rule to index of rule chain
{
Name: "insert",
Usage: "insert a rule at the specified index of the rule chain",
Aliases: []string{"ins"},
Action: rulesInsert,
Flags: rulesInsertArgs,
},
// remove existing command
{
Name: "remove",
Usage: "remove an existing rule from the rule chain",
Aliases: []string{"rem"},
Action: rulesDelete,
Flags: rulesRemoveArgs,
},
// flush all rules from chain
{
Name: "flush",
Usage: "remove all rules from the rule chain",
Action: rulesFlush,
Flags: rulesFlushArgs,
},
},
},
// rule options commands
{
Name: "default",
Aliases: []string{"dfault", "d"},
Usage: "modify firewall rule defaults",
Action: ruleoptsDisplay,
Subcommands: cli.Commands{
{
Name: "allow",
Usage: "set inbound/outbound's default to allow packets",
Aliases: []string{"a"},
Action: ruleoptsAllow,
Flags: ruleoptsAllowArgs,
},
{
Name: "deny",
Usage: "set inbound/outbound's default to deny packets",
Aliases: []string{"d"},
Action: ruleoptsDeny,
Flags: ruleoptsDenyArgs,
},
},
},
// whitelist commands
{
Name: "whitelist",
Aliases: []string{"white", "w"},
Usage: "modify firewall whitelist",
Action: whitelistDisplay,
Subcommands: cli.Commands{
{
Name: "append",
Usage: "append an ip-address to the whitelist",
Aliases: []string{"app"},
Action: whitelistAppend,
Flags: listAppendRules,
},
{
Name: "remove",
Usage: "remove an ip-address from the whitelist",
Aliases: []string{"rem"},
Action: whitelistRemove,
Flags: listRemoveRules,
},
},
},
// blacklist commands
{
Name: "blacklist",
Aliases: []string{"black", "b"},
Usage: "modify firewall blacklist",
Action: blacklistDisplay,
Subcommands: cli.Commands{
{
Name: "append",
Usage: "append an ip-address to the blacklist",
Aliases: []string{"app"},
Action: blacklistAppend,
Flags: listAppendRules,
},
{
Name: "remove",
Usage: "remove an ip-address from the blacklist",
Aliases: []string{"rem"},
Action: blacklistRemove,
Flags: listRemoveRules,
},
},
},
}

/***Functions***/

//getIP : collect given flag argument from context after verifying validity as a ip-range/ip-address/any
func getIP(c *cli.Context, flag string) string {
var ip = c.String(flag)
if _, _, err := net.ParseCIDR(ip); err != nil && net.ParseIP(ip) == nil && ip != "any" {
cliError(c, fmt.Sprintf("Flag: \"%s\" value is INVALID! (any/ip/[a network class])", flag))
}
return ip
}

//getIPWithDuplicate : collect ip and vefity that the ip is not already contained within a table
func getIPWithDuplicate(c *cli.Context, table string) string {
// get variables
ip := getIP(c, "ipaddress")
var exists int
// check if ip already exists
if err := db.QueryRow(
"SELECT IFNULL((SELECT 1 FROM "+table+" WHERE IPAddress=?), 0)", ip,
).Scan(&exists); err != nil {
cliError(c, fmt.Sprintf("SQL-ERROR: %s", err.Error()))
}
if exists == 1 {
fmt.Printf("IP-Address: %q is already within table: %q", ip, table)
os.Exit(0)
}
return ip
}

//cliError : return help page and then error
func cliError(c *cli.Context, message string) {
fmt.Printf("CLI-ERROR: %s\n\n", message)
cli.ShowSubcommandHelp(c)
os.Exit(1)
}

//defaultAction : without a command to execute this action in run
func defaultAction(c *cli.Context) error {
cli.ShowAppHelp(c)
return nil
}

//Run : run cli interface for sql/table input
func Run() {
app := cli.NewApp()
// base info
app.Name = "GoAway Firewall"
app.Usage = "better than ufw"
app.HelpName = "GoAway"
app.Description = "Small Local Firewall"
app.Version = "1.0.0"
app.Author = "Andrew Scott (AZCWR)"
// actions and commands
cli.HelpFlag = cli.BoolFlag{Name: "help", Usage: "shows the help page"}
app.Action = defaultAction
app.Commands = commands
// help templates
cli.AppHelpTemplate = helpMainPage
cli.CommandHelpTemplate = helpCommandPage
// run app
app.Run(os.Args)
}
16 changes: 16 additions & 0 deletions cli/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cli

import "io/ioutil"

/***Variables***/

// main help page
var helpMainPageBytes, _ = ioutil.ReadFile("cli/help.txt")
var helpMainPage = string(helpMainPageBytes)

// base command help page
var helpCommandPage = `Command: {{ .Name }} - {{ .Usage }}
{{if .Subcommands}}SubCommands:
{{range .Subcommands}}{{join .Names ", "}}{{"\t"}}{{.Usage}}
{{" "}}{{end}}{{end}}{{"\r"}}{{if .Flags}}Flags:
{{range .Flags}}{{.}}{{"\n "}}{{end}}{{"\r"}}{{end}}`
24 changes: 24 additions & 0 deletions cli/help.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
\\/////
|. .| .-""-.--.--.
( _\ | o ( GO-AWAY! )
| = | o '--'--'--'
|\___/
___/| \__
/` | '----' |`\ \\\\\\,
/ | | \ _/'' \\\ Commands:
/~% | FW ; \ \ D help, h - show this help page
/ /\/ |`\ \ \^ / rules, r - command dealing with all firewall rules
\ \ | | / / <\ />,_ white, w - command dealing with the firewall whitelist
`\ \| |/ /` / \Y/ /` \\ black, b - command dealing with the firewall blacklist
`\; |/` || # | | dfault, d - command dealing with all firewall rule defaults
(| |) || # | |
|_________| || # | | Global Flags:
| | | ||=[]=| | --help show this help page
|____|__| //| | /||\ --version, -v print the current version
\ | | | | |
| ) ) Hacker->| | | *For more help on individual commands:
/ | | ( ( | Command-Help: ./fwcli help [command]
|___|__| | | | Subcommand-Help: ./fwcli [command] help [sub-command]
\===|==| | | |
/ `-.`-. [_[___]
\______)__) (_(____|
Loading

0 comments on commit b9478fb

Please sign in to comment.