Coder Social home page Coder Social logo

web-port-knock's Introduction

Simple Web Port Knocking Implementation

What is the motivation of this repository?

Accepting TCP connections from the open internet is something I'm fairly paranoid about once packets are parsed by anything above the kernel. Especially if those services aren't web or SSH servers. Like a Minecraft server. I have no idea what the Minecraft wire protocol looks like, so I don't know exactly what I'm getting into when I open a Minecraft port to the open internet, but suffice to say I'd really rather not do that.

But I would like to let people selectively connect if they want. If I could ask my friends for their IP addresses, I could add their addresses to my firewall config and I'd be fine. But that's more work than I want to put in. Also many other people in the history of networked computing have had this exact same desire.

Port knocking is one way people used to do this, but that requires an understanding of how network protocols work and I'd rather not have to explain TCP to each one of my friends in the Discord before they can get on my server. Port knocking was basically an implementation of authorization based on "something you know," and a URL with some entropy is a thing I can give my friends that can serve the same purpose as a sequence of ports.

I didn't find anything else that really satisfied this use case...there's a node package out there but it seemed like overkill and maybe only for web traffic? Also I want to keep the amount of parsing that needs to be done as small as possible given that this service is going to be completely open to the internet. So I made one myself.

What this service does not do

Logging, periodic removal of whitelisted IP addresses, keep you from shooting yourself in the foot, HTTPS. Multiple authentication keys. Be guaranteed to work on anything other than a Linux distro similar to Ubuntu. IPv6 support. It's barebones and works for my specific threat model.

The main server.go basicaly listens on a port you define in an environment variable, waits for a GET request to a route you define in an environment variable, and runs a shell command hardcoded in the file. Also, in my estimation, you probably don't want any of that processing done by the service listening on the open internet. You might want HTTP logging and I might add that at some point, but you could also use tcpdump to log connections too and not lose out on any data. And it probably makes sense to do IP address cleanup with a separate service running on a cron job (I might add some logic for that too).

I have a simple systemd unit for running the service at startup, might add it at some point.

Port knocking is done in the clear, so not having TLS doesn't seem like a grave sin.

Usage:

Prerequsites:

You have ufw installed and enabled. If you want you can change the go file to use straight iptables but that's up to you to implement if you want. Also the user the server executes as must be able to run ufw with passwordless sudo. At least that's how I did it. I tried giving the binary CAP_NET_ADMIN but that doesn't let you mess with ufw rules. Maybe it works with iptables if you do it that way. Might test that and update it later. If you think it's a bad idea to give a binary listening on the open internet the ability to execute ufw with passwordless sudo drop an issue.

Build the server with go build server.go. Execute the server, providing the following 4 environment variables to the runtime:

  • LISTEN_SPEC An IP address colon port string, e.g. "127.0.0.1:8080", "10.0.0.2:1111". This is the what the go HTTP server will bind to. The thing open to the internet. If you're behind a router you'll probably wanna forward a port in.
  • HANDLER_ROUTE: A string containing at least 12 characters. The HTTP path that when browsed to will cause a command to be run to add a firewall rule. Probably should be hard to guess.
  • LOCAL_SERVICE_ADDRESS: The IP address the service you are protecting is running on. Specifically, this is what will be added to the "to" directive when a ufw rule is added.
  • SERVICE_PORT: The port the service you are protecting is running on. You also might be forwarding a port in if you are behind a router.

Then give your friends the HTTP URL that corresponds to your WAN IP address, HTTP listening port, and route.

License:

Dual licensed under the MIT license and the AntiLicense, see LICENSE.md.

web-port-knock's People

Contributors

mitchellharper12 avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.