Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard Connection Error: server is not an accepted origin #97

Closed
danmed opened this issue Jul 29, 2020 · 8 comments
Closed

Keyboard Connection Error: server is not an accepted origin #97

danmed opened this issue Jul 29, 2020 · 8 comments

Comments

@danmed
Copy link

danmed commented Jul 29, 2020

Hi again :)

My Rpi4 came in today and i followed the instructions on the blog post and can see the screen, however i can't use the keyboard.. It keeps coming up with a red box telling me there is a keyboard connection error (Transport Error)..

When i run "journalctl -f " i'm seeing :

INFO in server: http://192.168.2.11 is not an accepted origin.

I've set my hosts file to point the name "tinypilot" to my pi's IP address and that seems to allow it to work.. however it's not particularly useful if i have to change hosts files on all my machines...

I thought i had read in another post that this CORS stuff was fixed.. is there a way to fix it?

@mtlynch
Copy link
Contributor

mtlynch commented Jul 29, 2020

Oh, this is likely related to #83.

It sounds like you're accessing your Pi by IP address but it's expecting you to access it by hostname. Can you try accessing it by hostname (http://raspberrypi)?

It sounds like I should change this line to accept both the Pi's hostname and its IP.

@mtlynch mtlynch changed the title Keyboard Connection Error Keyboard Connection Error: server is not an accepted origin Jul 29, 2020
@danmed
Copy link
Author

danmed commented Jul 29, 2020

Oh, this is likely related to #83.

It sounds like you're accessing your Pi by IP address but it's expecting you to access it by hostname. Can you try accessing it by hostname (http://raspberrypi)?

It sounds like I should change this line to accept both the Pi's hostname and its IP.

Ideally i'd be hitting this from behind a reverse proxy.. so it would be like kvm.domain.co.uk.. but when i changed the hostname to that (after setting up the reverse proxy) it didn't like that either.. maybe it's because it's pointing to the IP.

using the hostname of the pi itself does seem to work (eg : tinypilot)

edit : So i altered the below line

cors_origin = os.environ.get('CORS_ORIGIN', 'http://' + local_system.hostname())

to

cors_origin = os.environ.get('CORS_ORIGIN', 'https://kvm.domain.co.uk')

and that's now working.. but ideally you're right.. it needs to be able to be hit from multiple addresses...

http://ipaddress
https://sub.domain.com
http://hostname

is there a way to make this happen? And maybe have the option to add to the list?

@peterberbec
Copy link

I think the TinyPilot should respond to all hostname/IPs. If someone is browsing to it, open. It'll be a whole nother animal if we implement TLS

@mtlynch
Copy link
Contributor

mtlynch commented Jul 29, 2020

@danmed - as a workaround right now, you can change this line:

https://github.com/mtlynch/tinypilot/blob/e175e83676f7d71a5a4471366be1a79816e2bf25/app/main.py#L33

And replace cors_origin with a list of hostnames/IPs you'd like to use like:

socketio = flask_socketio.SocketIO(app, cors_allowed_origins=[
    'http://ipaddress',
    'https://sub.domain.com',
    'http://hostname',
  ])

You could also just set it to '*', but then you're potentially vulnerable to CSRF attacks (another website could inject keystrokes that forward to your target device). It's not a realistic attack at this point in time because there are so few TinyPilot users, but I don't want to get sloppy with security now and have to break things later to get back to secure functionality.

I think the TinyPilot should respond to all hostname/IPs. If someone is browsing to it, open. It'll be a whole nother animal if we implement TLS

@peterberbec - It currently does respond to any hostname if you're just accessing the / route. The issue is that the keyboard forwarding happens via websockets implemented using socket.io, and socket.io relies on CORS settings to prevent CSRF.

Thinking about this more, the cleanest solution is probably to just accept all CORS origins but authenticate the initial handshake with a CSRF token to ensure the session originated from the TinyPilot browser tab and not an external tab. It's possible that flask_wtf is already protecting communcation with socket.io, in which case the CORS checks are redundant anyway.

I need to fire up Burp Proxy and play around with some requests to make sure third-party pages can't just send arbitrary keystroke messages into TinyPilot's websocket endpoint.

@peterberbec
Copy link

Would using a self-signed ssl cert that we install help?

@mtlynch
Copy link
Contributor

mtlynch commented Jul 29, 2020

Would using a self-signed ssl cert that we install help?

It will in the future, but not yet.

TLS protects you from an attacker who has access to your network traffic. The threat with CORS is a malicious website that you visit. Suppose you visit evil.com and that site uses JavaScript that instructs your browser to send a request to https://tinypilot/socket.io as you. For that attack, HTTP vs. HTTPS makes no difference, since any site you visit can still send requests to TinyPilot from your browser.

TLS will help, though, once we add authentication. Right now, TinyPilot assumes your network is secure. If an attacker is on your network, there's no reason for them to attack your session because they can simply visit TinyPilot from their machine and do whatever mischief they want. Once we support authentication, TLS will be useful for protecting authenticated sessions so that TinyPilot is secure even on untrusted networks.

@lignumaqua
Copy link

lignumaqua commented Jul 29, 2020

I don't know if this is the same issue, but my main machine is a Mac so to access TinyPilot I need to go to http://tinypilot.local rather than just http://tinypilot. However, that fails with a CORS error.

INFO in server: http://tinypilot.local is not an accepted origin.

I fixed it by changing (as you suggested above):

socketio = flask_socketio.SocketIO(app, cors_allowed_origins=[
    cors_origin,
    cors_origin + '.local',
  ])

@mtlynch
Copy link
Contributor

mtlynch commented Jul 29, 2020

Okay, it seems like it's harder than I thought to catch all the edge cases, and the protection we're getting with strict CORS checking is minimal to none, so I've switched to wildcard. I've added a work item to keep this on my radar #99.

If you re-run the quick-install commands, you should pick up the latest version which fixes this:

curl -sSL https://raw.githubusercontent.com/mtlynch/tinypilot/master/quick-install | bash -
sudo reboot

@mtlynch mtlynch closed this as completed Jul 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants