xpra icon
Bug tracker and wiki

Opened 2 weeks ago

Last modified 6 days ago

#2261 new enhancement

Dynamic Proxy Auth

Reported by: Mark Harkin Owned by: Mark Harkin
Priority: minor Milestone: 3.0
Component: server Version: 2.5.x
Keywords: Cc:

Description

I'd like to implement a docker setup where I have a proxy server with X number of xpra servers running behind it (scaled by replication). The proxy server would have a list of the ip's for each of the servers. When a user logs in, the user would be (dynamically) mapped to an ip from the list.

In docker this should be reasonably easy to implement as the list of ip's is available through dns lookup of tasks.${servicename}.

I think most of this can be implemented as a combination of sys and multifile auth. However I see an issue where I'd like the proxy to passthrough the password (challenge) to the server as for security I don't want the password stored on the proxy or no auth on the server. Is there anyway this can be achieved?

There would also have to be a way of recycling ip's when servers timeout or shutdown but I think that's also no so hard to implement. as the containers could just shutdown and a new container would spawn with new ip, then all that's left is to remove mappings where the ip no longer exists in the list.

An alternative approach would be to use a reverse proxy (nginx or similar) to do the work of the xpra proxy server. But in this case we would be forced to use websocket connection and would need to pass the user in a http header or something similar. And then implement the user ip mapping as describe above. But I think prefer an Xpra auth solution.

Change History (9)

comment:1 Changed 2 weeks ago by Antoine Martin

Owner: changed from Antoine Martin to Mark Harkin

See also: #2125

I think most of this can be implemented as a combination of sys and multifile auth.

multifile is going to be deprecated, use sqliteauth instead. (it is better in every way)

I'd like the proxy to passthrough the password (challenge) to the server as for security I don't want the password stored on the proxy

We could forward authentication requests to the client.
OTOH, it should work and I don't see why we're not doing it already.

There would also have to be a way of recycling ip's when servers timeout or shutdown

With auto-registration, via mdns or other technique, the proxy could keep a list of available servers.

I would really like to get this into the 3.0 release cycle.

comment:2 in reply to:  1 Changed 2 weeks ago by Mark Harkin

See also: #2125

Yes, that looks like a more generic solution, than the docker specific one metioned.

I think most of this can be implemented as a combination of sys and multifile auth.

multifile is going to be deprecated, use sqliteauth instead. (it is better in every way)

Yes, I was leaning towards using no file/db and storing the server list and user/server mapping in memory but sqlite db would work also.

I would really like to get this into the 3.0 release cycle.

Great to hear, #2125 and passthrough auth would be the majority of the work here, server recycling should be relatively easy after that.

comment:3 Changed 2 weeks ago by Antoine Martin

Owner: changed from Mark Harkin to Antoine Martin
Status: newassigned

passthrough auth would be the majority of the work here

Lemme take care of that in the next few weeks.

server recycling should be relatively easy after that.

Ideally, the mdns method can be made generic enough: a sort of server registry that can be manipulated via mdns or whatever backend we want to add later.

comment:4 Changed 9 days ago by Antoine Martin

Owner: changed from Antoine Martin to Mark Harkin
Status: assignednew

Updates:

  • r22387: better error handling in proxy instance
  • r22388: only flush_then_close once since we can call the proxy instance cleanup multiple times
  • r22389 only log the proxy instance shutdown message the first time
  • r22390 + r22392 + r22393: better? signal handling (buggy with python multiprocessing: Python | Multiprocessing and Interrupts)
  • r22391 close client connection if we receive an unexepcted message
  • r22394 use strings and simplify
  • r22395 bug in v2.5.x
  • r22397 authentication pass-through
  • r22398 + r22399 support clients connecting with authentication credentials via unix domain sockets, ie: xpra attach socket://username:password/var/run/user/1000/hostname-displayno

This works for me - tested with both python2 and python3, run all the commands as the same user:

  • start a tcp server with password authentication:
    echo -n 123456 > password.txt
    xpra start --no-daemon :20 --start=xterm --auth=file,filename=./password.txt -d auth
    
  • start a proxy with no authentication:
    xpra proxy --no-daemon --bind-tcp=0.0.0.0:14500 --tcp-auth=none -d auth,proxy
    
  • connect the client via the proxy:
    xpra attach tcp://$USERNAME:123456@localhost:14500/ -d auth,notify
    
Last edited 8 days ago by Antoine Martin (previous) (diff)

comment:5 Changed 8 days ago by Mark Harkin

I think I'm missing something in your example. Doesn't the proxy just create a server on a new display? what would bind it to use :20 ?

Thanks.

comment:6 Changed 8 days ago by Antoine Martin

Doesn't the proxy just create a server on a new display? what would bind it to use :20 ?

If there is only one existing session available for the user, that's the one that will be selected.

comment:7 in reply to:  6 Changed 8 days ago by Mark Harkin

If there is only one existing session available for the user, that's the one that will be selected.

I'm having trouble replicating that setup, I'll keep working on it but assuming this should also work for a proxy spawned server I'm getting the following error using html client:

2019-04-14 09:16:40,950 Warning: client expects an authentication challenge,
2019-04-14 09:16:40,950  sending a fake one
2019-04-14 09:16:41,585 New unix-domain connection received on /run/user/1000/xpra/2c4c0fa210d0-0
2019-04-14 09:16:42,035 New unix-domain connection received on /run/user/1000/xpra/2c4c0fa210d0-0
2019-04-14 09:16:42,085 New unix-domain connection received on /run/user/1000/xpra/2c4c0fa210d0-0
2019-04-14 09:16:42,883 Handshake complete; enabling connection
2019-04-14 09:16:42,895 Error setting up new connection for
2019-04-14 09:16:42,895  Protocol(unix-domain socket:/run/user/1000/xpra/2c4c0fa210d0-0):
2019-04-14 09:16:42,895  client failed to specify any supported encodings
2019-04-14 09:16:42,895 Disconnecting client Protocol(unix-domain socket:/run/user/1000/xpra/2c4c0fa210d0-0):
2019-04-14 09:16:42,895  server error (client failed to specify any supported encodings)

comment:8 Changed 8 days ago by Antoine Martin

2019-04-14 09:16:42,895 server error (client failed to specify any supported encodings)

You're seeing this when the client is expecting the server to send a challenge but it doesn't send one.

Last edited 8 days ago by Antoine Martin (previous) (diff)

comment:9 Changed 6 days ago by Mark Harkin

I'm guessing the proxy uses dbus to find the server, I can't do this in a docker container and haven't got a decent setup outside so will probably hold off on testing this until after #2125.

After looking into the mdns setup and #2125. The functionality I think is needed is something like:

  • servers report active and max no. of connections through mdns
  • proxy selects server with least active connections and rejects if all servers are at maximum.
Note: See TracTickets for help on using tickets.