98 lines
5.9 KiB
Markdown
98 lines
5.9 KiB
Markdown
# Amethyst Web Server
|
|
|
|
## A word of warning!
|
|
Currently Amethyst is in very early alpha stage, a lot of things will be broken, names won't be correct,
|
|
promised features missing, but I'm very much working on it live!
|
|
Every save I do increments the build number by 1, I won't publish all of them, but some of them will be published.
|
|
Once a milestone is hit (e.g. a new feature fully implemented), I'll publish a release!
|
|
|
|
## Currently working features:
|
|
* New configuration is ~95% done, most features work.
|
|
* Fixed **A LOT** of unreported bugs from the old code.
|
|
* More resilliency against errors.
|
|
* Improved security.
|
|
* Proxy almost working!
|
|
|
|
## Project status:
|
|
Amethyst will stay in beta for a while, I want all features to work, but I will make pre-release versions that are mostly stable.
|
|
They can be found as the `amethyst-prerel-0.a.b` releases. I won't guarantee 100% stability, but waay more than just some random build.
|
|
|
|
## Install instructions:
|
|
Install Python, execute `amethyst.py` and change the provided config.
|
|
|
|
## Minimum requirements:
|
|
Python 3.10+
|
|
And whatever PC that happens to run that.
|
|
I recommend Python 3.12 or above though, with a PC running:
|
|
* Windows 8.1+
|
|
* macOS 10.15+
|
|
* Linux 4.19+
|
|
* FreeBSD 13.2R+
|
|
* Some other somewhat recent OS.
|
|
|
|
## The webserver itself:
|
|
The Amethyst webserver is meant to be easy to use and configure. Its configuration takes inspiration from nginx and Caddyfile.
|
|
The language the configuration is made in is AmethystConf.
|
|
The default config is as follows:
|
|
```amethystconf
|
|
host * {
|
|
directory:./html
|
|
pesmode:0
|
|
block-ua:match("Discordbot")
|
|
index:index.html
|
|
}
|
|
|
|
globals {
|
|
http:1
|
|
https:1
|
|
port:8080
|
|
https-port:8443
|
|
key:./key.pem
|
|
cert:./cert.pem
|
|
max-length:8192
|
|
}
|
|
```
|
|
It uses a key-value syntax, and uses a `:` as its seperator. A few key directives:
|
|
`host`, followed by a hostname signifies a host that will be available. Similar to nginx's `server_name` directive.
|
|
`globals` signifies all values that are of global importance, like the key and certificate file.
|
|
`directory` signifies the directory to look in for files on that specific host.
|
|
`index`, while not in the default config, signifies what path should be returned if the client only asks for `/` (or any subpaths without files).
|
|
`pesmode` signifies if the PES mode must be enabled, allowing the server to run custom Python code to manipulate the request or file further.
|
|
`block-ua` signifies if a specific (or loosely matched) User-Agent must be blocked from accessing the site.
|
|
`proxy` signifies if a the server needs to get the response from a different (remote) server but still needs to be available at this host.
|
|
`max-length` signifies the maximum length a request may have.
|
|
AmethystConf has only 4 datatypes: `String`, `Boolean`, `Function` and `None`. A quick rundown:
|
|
`String` is the everything datatype. Everything is assumed to be a `String` unless it falls under the other categories.
|
|
`Boolean` is the datatype used to enable/disable features. A `Boolean` can have one of two possible values: `1` or `0`.
|
|
`Function` is the datatype used in `match()`, it signifies that the parser has to do some work on this string before it can use it.
|
|
`None` is the datatype assigned to any key without a value.
|
|
## PES (Python Extension Script)
|
|
The PES (Python Extension Script) is one of Amethysts main selling points. It's a new type of a dynamic page. A PES file is pretty much a
|
|
Python script with some conventions. Currently it is in very alpha form. It will be heavily improved upon to make sure even people with no
|
|
Python knowledge can work with it. Here's how it works:
|
|
If PES mode is enabled, the request is sent to the `pes.py` script, more specifically, the `on_request(req)` function of the `PES()` class.
|
|
From there, the decoded request is given to you to play with. All of Amethysts request and file processing tools are available, and soon
|
|
a function will be added to hand the request back to Amethyst, if it is deemed not suitable for PES mode.
|
|
Once you're done manipulating the request, all you have to do is call `return self.build_response(http_status_code, resp_body, mimetype)` and Amethyst will handle the rest.
|
|
A few examples of what can be achieved with PES mode without writing any other language than Python, HTML and CSS:
|
|
* Showing a random image from the `/pics` folder upon requesting `/randompic` from the server
|
|
* Dynamically updating the time on a website
|
|
* Create a complex calculator
|
|
* Upload files to the server
|
|
* Lock down webpages with a login prompt.
|
|
* And much, much more.
|
|
|
|
While it might not be able to create truly dynamic pages (since PES runs server-side, not client-side), it is dynamically static, basically, it's a dynamic page until it's rendered
|
|
in browser, where it's static, as PES cannot change anything there.
|
|
**WARNING!**
|
|
PES is an advanced feature! You can absolutely compromise the security of your webserver by having a misconfigured PES file. While Amethyst still has a few protection measures built-in
|
|
that activate before any request reaches the PES, but some are bypassed unless manually invoked in the PES. Because of that, here's a general user advisory:
|
|
* Use `self.fh.read_file(file_path, host=None)` instead of `open(file_path)` because of file inclusion or directory traversal concerns.
|
|
* Use `self.fh.write_file(file_path, host=None)` instead of `open(file_path)` because of file inclusion or directory traversal concerns.
|
|
* **NEVER** allow the PES to run shell code!
|
|
* **NEVER** allow the PES to run **ANYTHING** uploaded via the internet!
|
|
* Try running as much of the code locally, getting data from the internet can not only take long, it can also pose a security risk.
|
|
|
|
The PES will **NOT** warn you if you have security issues, it's a very hands-off approach. The PES will happily run `sudo rm -rf / --no-preserve-root` if given the command and
|
|
setup for shell execution and not tell you until everything is gone. Prevent those scenarios by limiting what PES does as much as possible!
|