From OpenHome
Line 5: | Line 5: | ||
The primary goal for remote access was that it must be trivial for end users to setup. All communications are routed through a central server, avoiding any requirement for users to learn about port forwarding, static external IP addresses, setup firewall rules allowing incoming http connections etc. | The primary goal for remote access was that it must be trivial for end users to setup. All communications are routed through a central server, avoiding any requirement for users to learn about port forwarding, static external IP addresses, setup firewall rules allowing incoming http connections etc. | ||
- | This | + | This led to a strong secondary goal - this central server must be cheap for Node manufacturers to host. It is intended that tens of thousands of clients (homes) can be accommodated by a single server. When user numbers grow beyond this or the geographical spread of users makes a single server a bottleneck, minimal work will allow any number of additional servers to be deployed. |
In addition to the software in ohRemote, remote access requires some additional features in [[ohOs|ohOs]]. These are also described below. | In addition to the software in ohRemote, remote access requires some additional features in [[ohOs|ohOs]]. These are also described below. | ||
== How do I get it? == | == How do I get it? == | ||
- | + | [https://github.com/openhome/ohremote Source code] is available to selected partners from. Contact info@openhome.org if you require access. | |
== System Architecture == | == System Architecture == | ||
- | [diagram] | + | [diagram goes here] |
The server contains the following components: | The server contains the following components: | ||
Line 36: | Line 36: | ||
== Deployment == | == Deployment == | ||
- | Server | + | === Server === |
- | Node | + | All configuration options are contained in the file ohremote/scripts/config. |
+ | <br>Hosting the server on a box with 2 IP addresses is recommended. This allows both the ssh server and web services to operate on port 443. This port is used by https so is likely to be open for outbound requests on most firewalls. (An argument could be made for port 80 – as used by http. This is at least as likely to be open on firewalls but is more likely to be subject to packet inspection and blocked as our use here will appear different to traditional web access.) | ||
+ | |||
+ | === Node === | ||
The location of the remote access server must be set in the remote-access-server tag of ohos.ohconfig.xml. This file is generated from ohOs/src/Host/ Host.ohconfig.xml.template during a build or the generated file can be edited and ohOs restarted to apply changes. | The location of the remote access server must be set in the remote-access-server tag of ohos.ohconfig.xml. This file is generated from ohOs/src/Host/ Host.ohconfig.xml.template during a build or the generated file can be edited and ohOs restarted to apply changes. | ||
- | The Node must be capable of generating a RSA format SSH key. This is currently only supported on Linux; other platforms need to manually generate the keys and move them (named key.priv & key.pub) to the remote directory in ohWidget’s store. | + | <br>The Node must be capable of generating a RSA format SSH key. This is currently only supported on Linux; other platforms need to manually generate the keys and move them (named key.priv & key.pub) to the remote directory in ohWidget’s store. |
+ | |||
== APIs == | == APIs == | ||
Line 154: | Line 158: | ||
== Monitoring == | == Monitoring == | ||
- | + | === Server === | |
+ | Every 3 seconds, checks status of each component, restarting server if any component does not respond correctly. See ohremote/scripts/ohmonitor for details. | ||
- | + | === Node === | |
+ | Every 5 minutes, issues a HEAD request to the user-facing uri returned by register [link] web service (and then stored in registry). If this fails, disconnects from ssh server, stops (local) proxy server then repeats “Connect a registered node” use case. If connection fails, it is retried at randomised (but increasing) intervals thereafter. |
Revision as of 12:03, 6 March 2012
Contents |
ohRemote
ohRemote provides the set of server components used to access ohOs apps from outside the home.
The primary goal for remote access was that it must be trivial for end users to setup. All communications are routed through a central server, avoiding any requirement for users to learn about port forwarding, static external IP addresses, setup firewall rules allowing incoming http connections etc.
This led to a strong secondary goal - this central server must be cheap for Node manufacturers to host. It is intended that tens of thousands of clients (homes) can be accommodated by a single server. When user numbers grow beyond this or the geographical spread of users makes a single server a bottleneck, minimal work will allow any number of additional servers to be deployed.
In addition to the software in ohRemote, remote access requires some additional features in ohOs. These are also described below.
How do I get it?
Source code is available to selected partners from. Contact info@openhome.org if you require access.
System Architecture
[diagram goes here]
The server contains the following components:
- Stunnel – a SSL tunnel which allows secure communications between user/node and the server without server components having to understand SSL.
- A reverse proxy server – HaProxy. This directs web requests to the correct server component.
- Web server, provided by Node.js
- Web services, implemented using Node.js
- SSH server, provided by dropbear
- Client authentication – a pluggable authentication module used by the ssh server when deciding whether to accept a connection request from a Node.
- Databases, provided by MySQL
The Node contains the following components:
- Standard node software
- Provider for RemoteAccess UPnP service [link]
- Remote access settings registry (currently combined with provider). This stores username, password, user-facing control url & node-facing web services url
- Proxy server. This connects to the remote access server’s ssh server and listens for requests, forwarding them to the appropriate locations on the standard node web server. The proxy server uses standard .NET classes – HttpListener for the server and HttpWebRequest to forward requests.
The remote client contains the following components:
- Any web browser supported by the Node UI.
Deployment
Server
All configuration options are contained in the file ohremote/scripts/config.
Hosting the server on a box with 2 IP addresses is recommended. This allows both the ssh server and web services to operate on port 443. This port is used by https so is likely to be open for outbound requests on most firewalls. (An argument could be made for port 80 – as used by http. This is at least as likely to be open on firewalls but is more likely to be subject to packet inspection and blocked as our use here will appear different to traditional web access.)
Node
The location of the remote access server must be set in the remote-access-server tag of ohos.ohconfig.xml. This file is generated from ohOs/src/Host/ Host.ohconfig.xml.template during a build or the generated file can be edited and ohOs restarted to apply changes.
The Node must be capable of generating a RSA format SSH key. This is currently only supported on Linux; other platforms need to manually generate the keys and move them (named key.priv & key.pub) to the remote directory in ohWidget’s store.
APIs
Server Web Services
1. To register for remote access, including selecting a username
URL: [server_url]/register Body: <register> <username>[Proposed username]</username> <uidnode>[Node’s UDN]</uidnode> <sshkey>[Contents of public key]</sshkey> </register>
Returns (success):
<result> <success>[Proposed username]</success> </result>
Returns (failure):
<result> <error>Username exists</error> <suggestionlist> <suggestion>First suggested free name </suggestion> <suggestion>Second suggested free name </suggestion> <suggestion>etc.</suggestion> </suggestion> </suggestionlist> </result>
2. To clear an account - (deregister interest in remote access, remove username)
URL: [server_url]/remove Body: <remove> <uidnode>[Node’s UDN]</uidnode> </remove>
Returns (success):
<result> <success>TBD - Chris</success> </result>
Returns (failure):
<result> <error>TBD - Chris</error> </result>
3. To get connection details for the ssh tunnel
URL: [server_url]/getaddress Body: <getaddress> <uidnode>[Node’s UDN]</uidnode> </getaddress>
Returns (success):
<result> <success> <sshserver> <address>[Ssh server host (or address)]</address> <port>[Ssh server port to connect to]</port> </sshserver> <portforward> <address>[Address for remote port forwarding]</address> <port>[Port for remote port forwarding]</port> </portforward> </success> </result>
Returns (failure):
<result> <error>TBD - Chris</error> </result>
Node web service
(RemoteAccess service description)
Use cases
Register new Node
- User brings up their Node UI inside the home
- User enters desired username & password
- Provider for RemoteAccess server is called for SetUserName [link] action
- Provider calls register[link] web service
- Registration web service on remote access server is called (via Stunnel then HaProxy)
- If requested username is available, registration service adds a record to the Login Database. Otherwise, it generates a list of similar usernames which are still available and returns this as part of an error.
- Assuming registration succeeded, Username is added to remote access registry. SetUserName action returns success.
- UI calls SetPassword action. Password is added to remote access registry and action returns success.
- UI calls SetEnable action. Enabled state is set in remote access registry. Enabling remote access is then covered by the next use case…
Connect a registered Node
- Happens either when SetEnable action is called or ohOs starts when remote access was previously enabled.
- Provider for RemoteAccess service calls getaddress [link] on Node Login service (via Stunnel then HaProxy)
- Node Login service checks that node has been previously registered (by checking for node’s udn in Login Database). If the node is unregistered, an error is returned.
- Node Login service calls Port Finder service to determine which port of the ssh server the node should connect to.
- Port Finder service determines a free port. Node Login service writes node udn, port and status (pending) to the Session Database.
- Home node now has approx 1 minute to connect to the ssh server. The Node Login service periodically checks the Session Database and removes records that have been pending for longer than 1 minute.
- Node Login service checks config file to determine ssh server host name and IP address/port to bind to for remote port forwarding. These 3 details plus the port determined above are returned to the home node.
- Home node starts its proxy server. This is currently hard-coded to listen on port 55170.
- Home node connects to ssh server. Server uses PAM SQL Lookup to validate ssh key used in connection request against key in Login Database. Server then changes status of node’s record in Session Database to ‘connected’.
- Home node sets up remote port forwarding for the port its proxy server is listening on.
User connects remotely
- User enters the url returned by the node registration process into their web browser.
- This reaches the Login web service (via Stunnel and HaProxy).
- The url path is the user name that was selected during registration. Login service looks this up in Login Database and redirects the request to HaProxy with the path changed to the node udn which matches the username.
- HaProxy uses the node udn to look up ssh server address/port in the Session Database.
- HaProxy forwards the request to the appropriate address/port on the ssh server.
- Ssh server forwards the request to the appropriate proxy server on a home node.
- Home node checks for the presence of a login cookie in the request. If this is missing, the request is redirected to a login page hosted by the home node.
- When the first request completes, HaProxy sets a session cookie noting the Session Database row id for this user.
- The user’s web browser displays the login page prompting for username and password. The results from this are sent to the home node’s proxy server which checks them against the data in its remote access registry. If the login is valid, another session cookie is set and the user is redirected to the root of the home node’s proxy server.
- The user’s web browser issues a GET request for ‘/’. HaProxy uses its cookie to find the correct ssh server address/port. (This may come from either the session database or an in-memory cache.) The home node’s proxy server manually forwards the request to the web server home UIs are available from, applying minor rewrites (such as compression) to the response.
Monitoring
Server
Every 3 seconds, checks status of each component, restarting server if any component does not respond correctly. See ohremote/scripts/ohmonitor for details.
Node
Every 5 minutes, issues a HEAD request to the user-facing uri returned by register [link] web service (and then stored in registry). If this fails, disconnects from ssh server, stops (local) proxy server then repeats “Connect a registered node” use case. If connection fails, it is retried at randomised (but increasing) intervals thereafter.