tobychui / zoraxy

A general purpose HTTP reverse proxy and forwarding tool. Now written in Go!
https://zoraxy.aroz.org
GNU Affero General Public License v3.0
3.09k stars 188 forks source link

[ENHANCEMENTS] Restructure the proxy functions #95

Closed Cerothen closed 9 months ago

Cerothen commented 10 months ago

Is your feature request related to a problem? Please describe. "Virtual Directory" entries cant be defined per subdomain (as far as I can tell the virtual directories are always applied to the naked domain or perhaps every domain?)

Describe the solution you'd like I am willing to work on implementing the changes myself as needed or have some assistance on the back end components. I have mocked up an alternative to the webUI for the HTTP proxy listing. I wont bother continuing if this doesnt align with the direction you are interested in for the project.

screencapture-10-20-20-200-8000-2024-01-08-03_36_49

The following code block is an example of the JSON that the API would serve.

    const developmentRecords = [
        { // First Entry shows all the settings and their defaults
            enabled: true, tls: true, auth:0, host:'test1.host.tld', 
            dest: [
                {enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}, // Multiple to support failover / load balancing
            ],
            locations: [
                { enabled:true, uri:'/_matrix/client', dest: [
                    {enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},
                    {enabled:false,tls:false,host:'127.0.0.1:1234',uri:undefined},
                ],},
                { enabled:true, uri:'/.wellknown/carddav', dest: [
                    {enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},
                ],},
                { enabled:true, uri:'/.wellknown/caldav', dest: [
                    {enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},
                ],},
            ], 
            config: {
                basicAuthUsers: [{uuid:'5cc724c3-d4b2-426e-baa8-d97ca07c81f5',name:'test1',pass:'serversideonly',enabled:true,},{uuid:'a4fcd479-1e2e-4eb4-b54a-b2d2ced080e2',name:'test2',pass:'serversideonly',enabled:false},],
                basicAuthGroups: [{uuid:'1b0f261c-e991-4bfe-9ec8-eb0c0751c1f1',name:'group1',enabled:true}],
                authService: {
                    url: '',
                    headers: [],
                },
                timeouts: {
                    connect: 60000,
                    read: 300000,
                    send: 300000,
                },
                uptime: {
                    enabled: true,
                    url: undefined, // Alternate URL for heartbeat
                },
                statistics: {
                    // Something
                },
            }
        },
        {enabled: true, tls: true, auth:0, host:'test2.host.tld', dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
        {enabled: true, tls: false, auth:1, host:'test3.host.tld', dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
        {enabled: false, tls: true, auth:0, host:'test4.host.tld', locations: [{ enabled:true, uri:'/_matrix/client', dest: [{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},],},], dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},]},
        {enabled: true, tls: true, auth:2, host:'test5.host.tld', dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
        {enabled: false, tls: false, auth:0, host:'test6.host.tld', dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
        {enabled: true, tls: true, auth:1, host:'test7.host.tld', dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
        {enabled: false, tls: true, auth:2, host:'test8.host.tld', locations: [{ enabled:true, uri:'/_matrix/client', dest: [{enabled:true,tls:false,host:'127.0.0.1:4321',uri:'/_matrix/element'},],},{ enabled:false, uri:'/_matrix/federation', dest: [{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined},],},], dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
        {enabled: true, tls: true, auth:0, host:'test9.host.tld', dest:[{enabled:true,tls:false,host:'127.0.0.1:1234',uri:undefined}]},
    ];

Additional context This would likely involve some significant rework on the backend as well for how the proxies are setup, organized and executed. The below file shows the mockup presented in the above image

https://github.com/Cerothen/zoraxy/blob/c3054bbfaca6bc59963461a3eb309b5fe4efc78e/src/web/components/proxy_layer5_http.html

tobychui commented 10 months ago

@Cerothen Love your idea! This changed how Zoraxy works from a reverse proxy design for serving one site to a system that serve multiple sites. However a few design I might need your elaboration, as here are a few items that confuses me on how they are suppose to work

  1. Can you explain what are the two locks are on each of the domain entry?
  2. For a UI this complex, do you have any ideas on the RWD interface on mobile devices? I kind of worry about if this design is used, mobile users (like me who always outside and need to manage dozens of servers) will have difficulties managing their sites
  3. Do you have a mockup on the edit interface? I think the way on how entries is edited might need to change from in-place-edit to something else to make the UI less complex, but before making this decision, I want to hear your view on this.
  4. For a single entry that contains two destination, is it fallback or load-balancer? 圖片
  5. I guess there is no way (after these change) we still keep the legacy reverse proxy function in places (as the required architecture change will make it impossible to keep backward compatibility), maybe we need to set a larger goal for next major release just for this change.
Cerothen commented 10 months ago

I can certainly explain the intent for your questions. I tried to deploy zoraxy recently but hit few roadblocks in replicating my existing nginx proxy manager setup around customised virtual directories and some other small things. So I thought I'd I could find the time I would try to contribute to growing this project since I like the idea of a single binary reverse proxy.

  1. This is my bad I started with image logos initially that were more descriptive but decided to fall back to the CSS themes included icons for visual consistency. Left to right we have enabled (if the proxy is enabled), SSL/TLS (if that domain has a valid SSL certificate and SSL is enabled), authentication (if that domain is using authentication eg none/basic/mod_auth).
  2. I didn't tackle any responsive items in this example, but the first three columns serve some quick controls and info and aren't all that important, they could be hidden on narrow screens. I wasn't able to get the table to be sortable properly without breaking but I'm not sure that's critical, the sorting could always be done before the row render.
  3. I didn't tackle the edit modals since I didn't want to put the effort in if it wasn't a direction you were interested in going for this project. I didn't envision in place edits just the row at the bottom to add new domains to the proxy even on a narrow display it would only show the domain, destination and add action. Once a proxy is added then the user can hit the edit button for the currently future popup modal which would let them do the more complex operations or basic edits.
  4. I didn't really have to many plans for the multiple item destinations, I just was planning for it in case it was useful in the future I think 95% of people would only ever have one, it would be for loadbalancing/failover though.
  5. I didn't think the legacy ones would stay at all after these changes took place, it was more just so I could flip around in the views arbitrarily.

All in all it does suggest some significant changes which I can appreciate could be a lot of work. I'm not all that familiar with golang but I have always been interested in learning (I have plenty of JavaScript experience since I mostly tackle web applications though nodejs or PHP). The intent was that the edit dialogs would be somewhat more descriptive and friendly while also expanding what the proxy is able to accomplish overall and get it to general feature parity with NPM.

Again it's not a requirement, I thought it would be interesting to try and contribute so that a competitor to NPM exists that's a single binary and doesn't need docker.

Cerothen commented 10 months ago

A few ultra quick table responsive mockups

screencapture-10-20-20-200-8000-2024-01-08-16_01_48 screencapture-10-20-20-200-8000-2024-01-08-16_01_16 screencapture-10-20-20-200-8000-2024-01-08-16_00_33 screencapture-10-20-20-200-8000-2024-01-08-15_59_59

tobychui commented 10 months ago

@Cerothen I really like your idea. However as I am working on my Master thesis right now, I don't really have much free-time to work on big changes like this at the moment. I will keep this enhancement here and once I got the time, I will start working on this.

Again, thanks so much for your great ideas!

Cerothen commented 10 months ago

No problem at all. I have just been exploring the GoLang tooling around reverse proxies, that I can can better understand their structure.

tobychui commented 9 months ago

Here are some updates 圖片

I decided to move virtual directory under each of the host (instead of a global one) as suggested by multiple issues.

圖片

For host, wildcard is also added so domains like *.foo.example.com can be used to provide shared router with multiple hosts. I still figuring out how to find which matching rule is best match, but currently I use longer-rule-first logic to handle scope overlap issues.

A lot of stuffs are still work-in progress, if anyone wanna take a look or help with the dev, please see the v3.0.0 branch (not backward compatible)