Commit graph

587 commits

Author SHA1 Message Date
Ben Busby
d4581797e7
Allow bypassing app router with FARSIDE_NO_ROUTER
Setting the aforementioned env var skips creation of the app router,
which is useful for running update.exs when the main app is already
running (otherwise there's a port conflict).
2021-11-15 20:09:34 -07:00
Ben Busby
5904c7cce4
Add searx example to demo table 2021-11-15 19:07:06 -07:00
Ben Busby
46a905d258
Add searx instances to services.json 2021-11-15 17:51:29 -07:00
Ben Busby
d35c358d80
Add Whoogle example to demo table in readme 2021-11-15 17:41:33 -07:00
Ben Busby
adbdd64b8c
Add whoogle instances to services.json
Whoogle is now eligible for Farside links. I haven't decided how I'd
like this implemented yet though. My idea is actually to refactor part
of Whoogle to work a bit better with this new "instance hopping"
paradigm -- namely, I'd like the config settings to be easily turned
into query params and appended to a farside link when a user's preferred
instance is blocked.
2021-11-15 17:18:12 -07:00
Ben Busby
97f1d26cbc
Include query params in service instance redirect
Query params ("/watch?v=dQw4w9WgXcQ" for instance) would previously be
lost in Farside redirects. This now includes them if they were included
in the original request.
2021-11-15 17:15:36 -07:00
Ben Busby
8ce5b04f51
Install crontab w/ script
This adds a couple of new scripts: install-crontab.sh and update.sh. The
install-crontab script does exactly that -- it installs a new crontab
that runs the update script every 5 minutes. An update script was added
to simplify the crontab a bit and to ensure the Elixir update script is
executed from the correct directory.
2021-11-15 16:44:26 -07:00
Ben Busby
c627f4d402
Update readme
Expanded readme to include a demo, a "how it works" section, and a general
overview of Farside's purpose.
2021-11-12 18:51:50 -07:00
Ben Busby
1ea7fdd2ec
Convert logo to SVG 2021-11-12 17:04:34 -07:00
Ben Busby
fec966ae59
Fix formatting 2021-11-12 14:40:05 -07:00
Ben Busby
3181bdfc80
Test ip rate limiting / throttling
Tests the throttling feature from the previous commit
2021-11-12 14:37:20 -07:00
Ben Busby
2d988a1239
Throttle incoming requests to 1/sec per ip
This introduces a way of throttling requests in a way that makes sense
for the purpose of the app. The app only supports redirecting to one
particular service when browsing, which would seldom be required more
than once per second for normal "human" browsing.

Without this, the service could easily be used to DOS multiple instances
at once. That being said, anyone concerned about someone DOS-ing
multiple instances at once should be aware that this would be trivial to
do with a simple bash script. This is simply a preventative measure to
hopefully deter people from trying to attack all public instances of
private frontends using farside.link.

Note that this throttling applies to all routes in the app, including
the homepage. This could be updated to exclude the homepage I guess,
but I'm not really sure what the use case would be for that.
2021-11-12 14:34:36 -07:00
Ben Busby
8ee4f308a4
Prevent same instance from being selected twice in a row
Introduces a new db key "<service>-previous" to track which instance was
last selected for a particular service. This allows for filtering the
list of available instances to exclude the instance that was last
picked, to ensure a (slightly) more even distribution of traffic.
There's still the possiblity of the following scenario, however:

:service instances > 2

/:service request #1 -> instance #1
/:service request #2 -> instance #2
/:service request #3 -> instance #1
/:service request #4 -> instance #2

where there are many ignored instances for a particular service. One
possible solution would be to implement the "<service>-previous" value
to be a list, rather than a single value, and push to that list until
only one element is left in the original "instance" array after
filtering, and then delete the "<service>-previous" key.
2021-11-10 12:19:37 -07:00
Ben Busby
71fb89e028
Move instance selection logic out of router
The process of selecting a random (working) instance for a specified
service has been moved out of the router and into lib/farside.ex. Moving
forward, the router itself should have very simple and easy to follow
logic for all paths.
2021-11-10 11:50:19 -07:00
Ben Busby
d334fc7695
Move Service struct def to its own module
Service struct now defined in lib/service.ex

This makes a bit more sense now that its a shared resource, rather than
just defining it only in the update.exs script.
2021-11-10 11:48:39 -07:00
Ben Busby
f33279c41b
Test for valid service redirects
Updates testing to iterate through all available services and validate
that each one correctly produces a 302 redirect.
2021-11-10 11:47:03 -07:00
Ben Busby
2189c9ddca
Simplify retrieval of service keys from redis
Can just use a wildcard in the initial keys query, rather than grabbing
all keys and filtering by service prefix.
2021-11-10 10:47:04 -07:00
Ben Busby
85123cb524
Use elixir 1.12 and otp 24 in build/test 2021-11-09 15:22:32 -07:00
Ben Busby
39c244d970
Skip querying all instances w/ "test mode"
Now allows setting FARSIDE_TEST to skip individually fetching each
instance, and instead just adds all of them to redis instantly. This
allows for an easier time in CI builds, for both the sake of speed and
to prevent a scenario where many simultaneous builds have a noticeable
impact on actual instances.
2021-11-09 15:12:58 -07:00
Ben Busby
1908c56ec6
Update README.md 2021-11-08 17:32:55 -07:00
Ben Busby
2fec7e77a2
Add readme banner 2021-11-08 17:30:45 -07:00
Ben Busby
56b9c52528
Display list of available instances on home page
This introduces a number of new changes:
- Services are now inserted into redis with a prefix prepended to the
key name. This allows for easier filtering to get only live instances.
- The home page now uses an eex template for displaying all live
instances for every service, determined by the last update
- A "last_updated" field was added
- farside.ex was added to contain all functionality related to querying
for instances (WIP)
- Other improvements
2021-11-08 17:08:19 -07:00
Ben Busby
8042dcad0c
Refactor project to new name
The name of the project is being refactored from Privacy Revolver to
Farside. The reasoning behind this is:
1. A shorter name is easier to remember
2. It can stand for "FOSS alternative redirecting service" (which I know
doesn't encapsulate all letters from "farside", but it's close enough).

This commit also includes improvements to the update script for
determining how far along the script is.
2021-11-07 12:29:06 -07:00
Ben Busby
06bb8403dd
Include protocol in service list
This circumvents the redirect encountered when sending a request to a
service without a specified protocol.
2021-11-07 12:28:06 -07:00
Ben Busby
a209ce2b13
Add CI status to readme, update description 2021-10-26 21:26:09 -06:00
Ben Busby
83bcad2eda
Add elixir CI 2021-10-26 21:21:00 -06:00
Ben Busby
e87973c5e5
Add basic router test
Obviously going to be expanded upon by quite a bit, but just wanted to
get started with basic testing sooner rather than later.
2021-10-26 00:23:31 -06:00
Ben Busby
d7a425509e
Update services.json 2021-10-24 13:36:14 -06:00
Ben Busby
2ea805bd88
Format with mix format 2021-10-23 15:18:13 -06:00
Ben Busby
76faebd234
Move constants to config, update string formatting
Not sure if this is the Elixir-y way to do this, but seems more logical
than hardcoding values such as redis connection.

Also went through and improved how string formatting was performed
throughout the app. Rather than "combining" <> "strings" this way, I'm
now just doing "#${variable}#{formatting}", which looks a lot cleaner.
2021-10-22 20:07:07 -06:00
Ben Busby
9a6d680213
Route service requests to an available instance
Router has been updated with a basic /:service/*glob endpoint, which
retrieves a list of instances for the requested service and picks a
random one to forward the user to (or falls back to a default instance
if none are found).

Should probably add a check to make sure the requested service exists
first.
2021-10-22 19:18:33 -06:00
Ben Busby
8f762d47fa
Setup basic Plug.Router framework for serving requests
Rather than use a full blown framework*, adding basic routing with
Plug.Router seems to make more sense, since I'm not planning on hosting
any content through this app. The app itself will just be endpoints for
all available services that redirect the user to an available instance
for the requested service.

Note that I might change my mind about this, but that's unlikely. At
most there would just be a home page with info about available
instances, but even then that seems kinda pointless. Trying to keep this
as absolutely simple as possible.

*like Phoenix
2021-10-22 18:28:12 -06:00
Ben Busby
edcab37c7d
Write results of update script to file for debugging
The update script now writes the available instances to a
.update-results* file (where previous runs have "-prev" appended to the
file name). This helps to see how instance availability changes between
runs of the script when debugging overall functionality of the app.
2021-10-22 18:07:59 -06:00
Ben Busby
4949ae22bb
Output available instances and fallback URL to redis
Once a list of available URLs has been determined for a particular
service, the list is written as "service -> [list of instances]" to a
local redis connection. These can then be used in the greater routing
logic to pick a random instance from the list, or use a fallback
instance if none are determined to be available.
2021-10-22 17:15:40 -06:00
Ben Busby
b0953f0777
Validate status code for all service instances
Updated to filter out all instances that either time out (I believe
default timeout for HTTPoison is 5s) or return a non-200 status code.
2021-10-21 21:15:58 -06:00
Ben Busby
cf8dfc5a85
Initialize update script
My initial thought for this: create a simple redis db for storing key
value pairs of instance -> list of live instances for each privacy front
end (libreddit, bibliogram, etc). A script executed on a certain
schedule would (in the background) check each instance to make sure it
isn't down or unreasonably slow. If the instance is available, add it to
a list of available instances in the db.

When a user navigates to the revolver url (something like
<url>/<service>/<...>), the app would pick a random value from the list
returned by redis.get('<service>') and forward the user to that
instance.

As a side note, this could instead load the instances json from a remote
source (like github or something) so that changes to instances don't
need to involve a redeploy of the entire app.
2021-10-21 17:07:43 -06:00
Ben Busby
be9606094c
Initial commit 2021-10-21 15:50:04 -06:00