-
Notifications
You must be signed in to change notification settings - Fork 33
Automagic socket sharing for net/tls connections via proxy server #702
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
base: master
Are you sure you want to change the base?
Conversation
47c7896 to
fafd7c4
Compare
|
Original TODO:
|
|
The floor is now open. |
|
Comment the first: the entire PR message is a thing of beauty. 🙈 |
src/colony/modules/_net_proxied.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment here to explain what this cert is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in f49d968
|
This PR is of good quality and most of my complaints are minor. I don't want to land this without at least some additional proxy-specific tests, which we should talk about over Zulip; otherwise this generally improves code quality and doesn't have any standout issues. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious, why object.create instead of new?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
streamProto becomes the prototype for an already-existing socket object (see @tcr's "I hate you" comment above ;-) and this bypasses calling the actual constructors again, only preparing the [think of it like a] "mix-in" we now need.
If it weren't for needing a link between socket instances and their associated tunnel (next two lines) the logic that uses this would just ProxiedSocket.prototype directly instead.
|
lgtm, will do more testing of this over the weekend. |
…n up test suite includes
…te insecure socket (see #697 for cause of silent fallback)
…T ahead of time ;-)
…se of not stack overflowing when proxy server not on LAN…
…for any more dev testing stuff
…luded by the existing un-delegation after auth)
…nd number past 60s)
0674dbe to
f01660a
Compare
This integrates a client for https://github.com/tessel/proxy into the runtime
net/tlsmodules. In this way, some of the built-in CC3000 WiFi module's limitations and quirks may be avoided. Socket number limitation is raised, and perhaps even IPv6 endpoints via proxy [untested].Overview
The proxy is enabled and optionally configured via the following
process.envkeys. These can be set manually, before anyrequirestatements that may cause the net module to be evaluated, or via thetesselCLI interface once tessel/t1-cli#167 is released.In short, you will need to at least provide
PROXY_TOKEN/TM_API_KEYto enable proxiednetconnections, andPROXY_TRUSTED=1once you understand its implications.Sample usage
Once the proxy settings are configured, they are applied automatically to all relevant outgoing network connections:
Configurable environment variables
PROXY_HOST(default:"proxy.tessel.io") — hostname or IP address of the proxy server you wish to use.PROXY_PORT(default:443) — the proxy server will be contacted on this port. Even though the client-proxy connection is not HTTPS, we use port 443 by default to help circumvent overly strict firewalls 🙈PROXY_CERT— If you are tunneling through your own proxy server and it uses a self-signed certificate, you will need to provide its public key in PEM format. The default value is empty, in which case the default certificate trust chain is used.PROXY_TRUSTED(default:0) — By default, onlynetsockets will be proxied, andtlswill use their own CC3K sockets directly. Set this to1to trust the proxy server with secure socket data; this disables end-to-end encryption! See important TLS information below for details.PROXY_IDLE(default:90e3) — The tunnel to the proxy will be closed if no new sockets are opened within this timeout. Set to0to leave the tunnel connected only while actively used, or set toInfinityto keep the tunnel open indefinitely once it is first used.PROXY_LOCAL— space separated list of hosts for which the net/tls libraries should still use direct (native CC3K) connections. Your list may include individual IP addresses (192.168.1.1), IP address ranges in CIDR notation (192.168.0.255/4), exact domain matches (www.example.com) or a domain including subdomains (.example.net). Default setting includes common LAN ranges andlocalhost` [xref: https://github.com/CC3K can't connect to localhost/127.0.0.1 [or even own network IP address?!] t1-firmware#60].PROXY_TOKENorTM_API_KEY(required) — to enable an proxy usage, you must provide a valid token used to authenticate with the proxy server. For the hosted server, this should be the API key displayed in your profile at https://oauth.tessel.io. For a self-hosted proxy, this will likely be yourAUTH_HARDCODEDpassword or whatever custom authentication you have configured. (PROXY_TOKENtakes precedence over the more generalTM_API_KEY.)Per-socket options
When using the options form of the
net.connectortls.connecthelpers, there is now an additional setting:{proxy:false}— you can force anetortlsconnection to bypass the proxy (i.e. use CC3K directly) via this extension to the normal socket options.The HTTP/HTTPS modules tend to forward their options objects into the respective network modules, so you may also be able to control proxying at that level as well. This has not been thoroughly reviewed, and connection-reuse via the default global Agent may interfere in unintended ways.
Important TLS information
Although the client-proxy "tunnel" connection is always done over a
tlssocket, it was impractical to connect the Tessel runtime's built-in TLS library to a proxied (virtual) socket. Therefore, there is no end-to-end encryption for proxied sockets: the proxy server has access to all data sent/received.By default, if you create an outgoing connection via the
tls(orhttps) module, the proxy tunnel will not be used — it will use a native CC3K socket to make a direct connection. If you trust the proxy server and would like it to handletlsconnections on your behalf, you will need to setPROXY_TRUSTED=1.Implementation details
There is a new quasi-"abstract base class"
Socketwhich now underlies the originalTCPSocketand the newProxiedSocketclasses. Should you create a socket viasocket = new net.Socket(), all expected method calls are buffered until you callsocket.connect(). At this point, the target host is examined and used (along with all other relevant settings) to determine which type of socket should be used. You socket instance is converted in-place to the appropriate "concrete" subclass and completes its initialization via Don't Try This At Home™ means.Now, if the connection is via a
TCPSocketit pretty much [mis-]behaves as it did before. If it is aProxiedSocket, however, then a whole different mechanism rolls into action. First, we check to see if there is already a tunnel open to the proxy server. If so, our job is relatively easy: just create a new "substream" (passing a tls/net flag to the server based on the local socket type) and forward the provided host/port information (and a few other methods/events) over to the proxy server.When no tunnel is active, one is set up by connecting to the proxy server, sending the authorization token, and waiting for its signal to proceed. Most of this is managed by way of the streamplex module, the proxy server and client just add back some of the socket-specific handling. Once all sockets using a tunnel are closed, the tunnel itself is shut down.
Any error on the underlying tunnel will cause it to be closed. The event will propagate to all subsockets, however, so a new tunnel can be re-established when a new proxied socket is opened.
An oracle concerning the CC3000
While tunneling all end-user sockets through a single proxy connection can avoid some pitfalls, any issue that would plague a single network socket will now plague all of your (proxied) sockets together. Beware. Beware!
Like such as in the this issue: tessel/t1-firmware#128