Capturing Envoy Data
Pursuant to my last post, I’ve written a simple man-in-the-middle proxy to intercept communication between the Envoy and the Enphase servers. The code is available here.
What it does⌗
As I detailed in my previous post, the Envoy sends data to Enphase via http POST
requests. The proxy intercepts these requests, extracts the XML data from the request, and writes it to a local file (by default in /var/spool/envoy
). It then forwards the request on to Enphase, and returns the reply to your Envoy.
In addition to extracting the XML data, the proxy also logs the complete contents (headers and message content) of the request and the reply to files.
How it works⌗
Out of the box, your Envoy configures itself automatically using DHCP. Possibly, you’ve configured it statically. In either case, it will typically be configured to connect via your default gateway – generally, your home router, cable modem, etc. In order to intercept the communication between the Envoy and Enphase, we insert another server between the Envoy and your network gateway. In the foollowing diagram, the dotted line represents the original communication path, while the solid lines represent the new communication path:
The intermediate system – which we’ll call the interceptor – will use a few tricks to redirect traffic destined for Enphase to the local proxy (which will log the data locally and then forward it on to Enphase).
Assumptions⌗
For the purposes of this article, we’ll assume that your Envoy is at address 192.168.1.100, and the address of the interceptor is 192.168.1.200.
I’m assuming that your interceptor is running Linux. It may be possible to accomplish the same thing with other tools, but I’m relying on the Linux netfilter subsystem (aka “iptables”) to perform certain key tasks.
Configuring the Envoy⌗
You will need to congfigure the Envoy to use your interceptor host as its default gateway.
- Go to the network connectivity page on your Envoy.
- If it’s checked, uncheck the “Use DHCP” setting and select the “Updating DHCP setting” button.
- Set the “Gateway IP” field to the address of your interceptor (192.168.1.200 in this example).
- Select the “Update Interface 0” button.
Configuring the interceptor⌗
Redirecting requests⌗
We need to configure the interceptor to redirect requests to the Enphase servers to a local application. We’ll add the following firewall rule:
iptables -t nat -A PREROUTING -s 192.168.1.100 -p tcp \
--dport 443 -j REDIRECT --to-ports 4430
This rule matches https (port 443) requests from your Envoy (192.168.1.100) and redirects them to port 4430 on the interceptor.
Note that this rule will be lost if you reboot your system. Making firewall rules persistent is beyond the scope of this article; consult the documentation for your distribution of choice.
Handling SSL⌗
My simple Python proxy doesn’t speak SSL, so we need to create a plain http request from the https request. Normally this would be difficult, but Enphase has made our life easier by not checking the validity of the SSL certificate. We’re going to use stunnel as an https-to-http proxy. Create a file called /etc/stunnel/envoy-ssl.conf with the following contents:
[https_in]
accept = 4430
cert = /etc/pki/tls/certs/localhost.crt
connect = 127.0.0.1:8080
Run stunnel with this configuration:
stunnel /etc/stunnel/envoy-ssl.conf
This assumes you have an SSL certificate in /etc/pki/tls/certs/localhost.crt. You will probably need to generate one, which again is left as an exercise to the reader.
Installing bottle⌗
The proxy relies on the bottle Python web framework, which is probably not installed on your system. The easiest way to get things going is to install a Python “virtual environment” with the appropriate modules. Create a new virtual environment:
virtualenv ~/env/envoy
And install bottle:
~/env/envoy/bin/pip install bottle
Creating directories⌗
By default the proxy will write data to /var/spool/envoy. You’ll need to make sure this directory exists and is writable by whatever account you’re using to run the proxy.
Running the proxy⌗
Now that you’ve got all the prerequisites in place, you should be able to start the proxy by running:
~/env/envoy/bin/python proxy.py
You should see something like this:
Bottle server starting up (using WSGIRefServer())...
Listening on http://127.0.0.1:8080/
Hit Ctrl-C to quit.
Assuming that everything else went as planned, sometime within the next five minutes you should see the proxy service a request from your Envoy:
localhost.localdomain - - [22/Feb/2012 09:03:57] "POST /emu_reports/
performance_report?webcomm_version=3.0 HTTP/1.1" 200 103
From this request you will end up with three files in /var/spool/envoy:
2012-02-22T09:03:01-0j1FFs.xml
This is the XML data from the Envoy and is probably the most interesting file.2012-02-22T09:03:01-ZMxw6b.request
This is the raw request from the Envoy.2012-02-22T09:03:02-NB4DbR.response
This is the response from the Enphase servers.
If you find some bugs, please let me know by creating a new issue here. Note that this is only for bugs in the code; if you need basic networking tutorials and so forth the Google has lots of help for you.