Skip to content
This repository has been archived by the owner on Feb 24, 2022. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingloo committed Aug 18, 2018
1 parent da0f69e commit 1f9d93a
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 0 deletions.
88 changes: 88 additions & 0 deletions DataTypes.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
namespace Hosts

module DataTypes =

open System
open System.IO

type ExitCodes =
| Success = 0
| ErrorServerTypeSwitchMissing = -1
| ErrorServerTypeUnknown = -2

let blackHole = "0.0.0.0"
//let directory = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)
let directory = Environment.CurrentDirectory
let addedHostsFilePath = Path.Combine (directory, "addedHosts.txt")
let excludedHostsFilePath = Path.Combine (directory, "excludedHosts.txt")
let customExtrasFilePath = Path.Combine (directory, "customExtras.txt")

type DnsServerType =
| Bind
| Unbound
| Windows
| Missing
| Unknown

type DnsServer = {
Name: DnsServerType
Format: string -> string
}

let dnsServerTypes : List<DnsServer> = [
{
Name = Bind
Format = (fun x -> "zone \"" + x + "\" { type master; file \"/etc/bind/zones/db.poison\"; };")
}
{
Name = Unbound
Format = (fun x -> "local-zone: \"" + x + "\" inform_deny.")
}
{
Name = Windows
Format = (fun x -> blackHole + " " + x)
}
{
Name = Unknown
Format = (fun x -> "# domain name server type unknown")
}
]

type DomainSourceType =
| AbuseCH
| MVPS
| SANS

type DomainSource = {
Name: DomainSourceType
Url: Uri
Format: string -> string
}

let domainSources : List<DomainSource> = [
{
Name = AbuseCH;
Url = new Uri("https://ransomwaretracker.abuse.ch/downloads/RW_DOMBL.txt");
Format = (fun raw -> if raw.StartsWith("#") then "" else raw)
}
{
Name = SANS;
Url = new Uri("https://isc.sans.edu/feeds/suspiciousdomains_Low.txt");
Format = (fun raw -> if raw.StartsWith("#") || raw.StartsWith("site") then "" else raw)
}
{
Name = SANS;
Url = new Uri("https://isc.sans.edu/feeds/suspiciousdomains_Medium.txt");
Format = (fun raw -> if raw.StartsWith("#") || raw.StartsWith("site") then "" else raw)
}
{
Name = SANS;
Url = new Uri("https://isc.sans.edu/feeds/suspiciousdomains_High.txt");
Format = (fun raw -> if raw.StartsWith("#") || raw.StartsWith("site") then "" else raw)
}
{
Name = MVPS;
Url = new Uri("http://winhelp2002.mvps.org/hosts.txt");
Format = (fun (raw: string) -> if raw.StartsWith("#") || String.IsNullOrWhiteSpace raw then "" else raw.Split(" ", StringSplitOptions.RemoveEmptyEntries).[1])
}
]
106 changes: 106 additions & 0 deletions Program.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
namespace Hosts

module Program =

open System
open System.IO
open System.Net.Http
open DataTypes

let writeMessage (message: string) =
use writer = Console.Error
writer.WriteLine(message)

let determineServerType args : DnsServerType =
let typeIdx = Array.tryFindIndex (fun elem -> elem = "-type") args
match typeIdx with
| Some idx ->
try
match args.[idx + 1] with // the domain type will be in the array position after "-type"
| "bind" -> Bind
| "unbound" -> Unbound
| "windows" -> Windows
| _ -> Unknown
with
| :? IndexOutOfRangeException as ex -> Unknown
| None -> Missing

let getLinesFromWebString (webString: string) (domainSource: DomainSource): Async<seq<string>> =
async {
let lines = new System.Collections.Generic.List<string>()
use reader = new StringReader(webString)
let mutable hasMoreLines = true
while hasMoreLines do
let! line = reader.ReadLineAsync() |> Async.AwaitTask
if line <> null then
let formattedLine = domainSource.Format line
match Uri.TryCreate("http://" + formattedLine, UriKind.Absolute) with
| true, _ -> lines.Add formattedLine
| false, _ -> ()
else
hasMoreLines <- false
writeMessage ("loaded " + lines.Count.ToString() + " lines from " + domainSource.Name.ToString() + " (" + domainSource.Url.AbsoluteUri + ")")
return lines :> seq<string>
}

let downloadDomainSource (domainSource: DomainSource) : Async<seq<string>> =
async {
try
use client = new HttpClient()
let! result = client.GetStringAsync(domainSource.Url) |> Async.AwaitTask
return! getLinesFromWebString result domainSource
with
| ex ->
writeMessage ("downloading (" + domainSource.Url.AbsoluteUri + ") failed: " + ex.GetType().Name + " (" + ex.Message + ")")
return Seq.empty
}

let getRemoteDomains domainSources : seq<string> =
domainSources
|> List.map downloadDomainSource
|> Async.Parallel
|> Async.RunSynchronously
|> Array.reduce (fun acc item -> Seq.append acc item) // turns an array of seqs into one seq of everything

let printLines (lines: seq<string>) =
use writer = Console.Out
lines
|> Seq.iter (fun line -> writer.WriteLine(line))

let printDomains (serverType: DnsServerType) (domains: seq<string>) =
domains
|> Seq.map (fun item ->
let dns = List.find (fun (y: DnsServer) -> y.Name = serverType) dnsServerTypes
dns.Format item)
|> printLines

let loadLinesFromFile filePath =
try
let lines = File.ReadAllLines filePath
writeMessage ("loaded " + lines.Length.ToString() + " lines from " + filePath)
lines
with _ ->
writeMessage (filePath + " was not found")
Array.empty

[<EntryPoint>]
let main args =
match determineServerType args with
| Unknown ->
writeMessage "! server type unknown !"
int ExitCodes.ErrorServerTypeUnknown
| Missing ->
writeMessage "! no domain type switch !"
int ExitCodes.ErrorServerTypeSwitchMissing
| serverType ->
let customExtras = loadLinesFromFile customExtrasFilePath
let addedHosts = loadLinesFromFile addedHostsFilePath
let excludedHosts = loadLinesFromFile excludedHostsFilePath
printLines customExtras
domainSources
|> getRemoteDomains
|> Seq.append addedHosts
|> Seq.except excludedHosts
|> Seq.distinct
|> printDomains serverType
int ExitCodes.Success
13 changes: 13 additions & 0 deletions test.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="DataTypes.fs" />
<Compile Include="Program.fs" />
</ItemGroup>

</Project>

0 comments on commit 1f9d93a

Please sign in to comment.