This add-on is operated by Fixie
Static IP addresses for outbound HTTP and HTTPS requests
Fixie
Last updated October 26, 2022
Table of Contents
- Provisioning the add-on
- Your static IP addresses
- Dashboard
- Local setup
- Using with Node
- Using with Ruby
- Using with Python
- Using with Java
- Using with Go
- Using with PHP
- Using with .NET
- Using with other languages
- End-to-end encryption of HTTPS requests
- Migrating between plans
- Removing the add-on
- Connecting through a single IP address
- Support
Fixie is an add-on that provides Heroku applications with a fixed set of static IP addresses for outbound requests. Fixie is language- and framework-agnostic.
Without Fixie, your Heroku application makes requests from an unpredictable and impermanent set of IP addresses. Because Heroku IPs are dynamic, it can be difficult to integrate Heroku applications with services that allowlist a fixed IP range, including certain APIs and services that operate behind a corporate firewall.
Fixie acts as a proxy for outbound traffic, tunneling your requests through a known IP address. Each Fixie subscriber is assigned a set of static IP addresses. These addresses can be used anywhere you need a fixed IP range: API providers, firewall configurations, etc.
Fixie provides customers with a standard proxy URL that can be used to make requests from any server-side language, including Ruby, Python, Node, Java, and Go. Fixie can also be used by CURL and other command-line tools. Fixie can proxy both HTTP traffic and HTTPS traffic.
Provisioning the add-on
Fixie can be attached to a Heroku application via the CLI:
A list of all plans available can be found here.
To add our free plan (the default):
$ heroku addons:add fixie
-----> Adding fixie to sharp-mountain-4005... done, v18 (free)
Once Fixie has been added, a FIXIE_URL
setting will be available in the app configuration and will contain the outbound proxy URL. This can be confirmed using the heroku config:get
command.
$ heroku config:get FIXIE_URL
http://fixie:your-token@your-subdomain.usefixie.com:80
Your static IP addresses
You can retrieve your static IP addresses in the “Account” tab of the Fixie Dashboard. Your IP adresses are listed under “Account Details.”
Your static IP addresses are also shown in the command line when you enable Fixie using the Heroku CLI:
$ heroku addons:add fixie
Adding fixie to sharp-mountain-4005… done, v18 (free)
Your static IP addresses are 54.174.229.200, 54.176.231.252
Dashboard
The Fixie dashboard can be used to monitor your Fixie usage, retrieve your Fixie URL, and retrieve your outbound static IPs.
The dashboard can be accessed by visiting the Heroku Dashboard and selecting the application in question. Select Fixie from the Add-ons menu.
The dashboard can also be accessed via the CLI:
$ heroku addons:open fixie
Opening fixie for sharp-mountain-4005…
Local setup
Environment setup
If you wish to use Fixie to proxy requests while developing locally, it is necessary to locally replicate the FIXIE_URL environment variable.
Though less portable, it is also possible to set local environment variables using export FIXIE_URL=value
.
Use Foreman to configure, run and manage process types specified in your app’s Procfile. Foreman reads configuration variables from an .env file. Use the following command to add the FIXIE_URL values retrieved from heroku config to .env
.
$ heroku config -s | grep FIXIE_URL >> .env
$ more .env
Credentials and other sensitive configuration values should not be committed to source-control. In Git, exclude the .env file with: echo .env >> .gitignore
.
Using with Node
Fixie works with both the standard http
and https
modules and with higher-level http clients, including the popular axios
library.
These examples assume the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
Using Axios:
const axios = require('axios');
const url = require('url');
const fixieUrl = url.parse(process.env.FIXIE_URL);
const fixieAuth = fixieUrl.auth.split(':');
axios.get('https://example.com', {
proxy: {
protocol: 'http',
host: fixieUrl.hostname,
port: fixieUrl.port,
auth: {username: fixieAuth[0], password: fixieAuth[1]}
}
}).then(response => {
console.log(response.status);
});
Using with Ruby
You can use Fixie with any Ruby http client. Included are example of using it with Net::HTTP
from the standard library and with popular rest-client
or faraday
gems.
These examples assume the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
Using rest-client
:
require 'rest-client'
RestClient.proxy = ENV["FIXIE_URL"]
response = RestClient.get("http://welcome.usefixie.com")
Using faraday
:
require 'faraday'
conn = Faraday.new(:url => "http://welcome.usefixie.com", :proxy => ENV["FIXIE_URL"])
response = conn.get
Using with httparty
:
fixie = URI.parse ENV['FIXIE_URL']
HTTParty.get(
"http://welcome.usefixie.com",
http_proxyaddr: fixie.host,
http_proxyport: fixie.port,
http_proxyuser: fixie.user,
http_proxypass: fixie.password
)
Using Net::HTTP
from the standard library:
require 'net/http'
_, username, password, host, port = ENV["FIXIE_URL"].gsub(/(:|\/|@)/,' ').squeeze(' ').split
uri = URI("http://welcome.usefixie.com")
request = Net::HTTP.new(uri.host, uri.port, host, port, username, password)
response = request.get(uri)
Using with Python
Fixie works with any http client library, including urllib2
from the standard library and third-party packages including the popular requests
package.
These examples assume the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
To route a specific request through Fixie using requests
:
import os, requests
proxyDict = {
"http" : os.environ.get('FIXIE_URL', ''),
"https" : os.environ.get('FIXIE_URL', '')
}
r = requests.get('http://www.example.com', proxies=proxyDict)
Using urllib2
to send a specific request through Fixie:
import os, urllib2
proxy = urllib2.ProxyHandler({'http': os.environ.get('FIXIE_URL', '')})
auth = urllib2.HTTPBasicAuthHandler()
opener = urllib2.build_opener(proxy, auth, urllib2.HTTPHandler)
response = opener.open('http://www.example.com')
html = response.read()
The urllib2
API is significantly more verbose than that of the requests
package. The requests
package is a better choice for most applications.
If you intend to route all outbound traffic through Fixie, a simpler option is to set the http_proxy
and https_proxy
environment variables. Both urllib2
and requests
honor the http_proxy
and https_proxy
environment variables, so you can route all outbound requests through Fixie using these environment variables:
import os, requests
os.environ['http_proxy'] = os.environ.get('FIXIE_URL', '')
os.environ['https_proxy'] = os.environ.get('FIXIE_URL', '')
requests.get("http://www.example.com")
Using with Java
You can use Fixie with any HTTP library. Popular options include Apache HttpClient and OkHttp.
These examples assume the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
A simple example using HttpClient:
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class FixieExample
{
public static void main(String[] args) throws Exception {
String fixieUrl = System.getenv("FIXIE_URL");
String[] fixieValues = fixieUrl.split("[/(:\\/@)/]+");
String fixieUser = fixieValues[1];
String fixiePassword = fixieValues[2];
String fixieHost = fixieValues[3];
int fixiePort = Integer.parseInt(fixieValues[4]);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(fixieHost, fixiePort),
new UsernamePasswordCredentials(fixieUser, fixiePassword));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider).build();
try {
HttpHost proxy = new HttpHost(fixieHost, fixiePort);
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
HttpHost target = new HttpHost("www.example.com", 80, "http");
HttpGet httpget = new HttpGet("/");
httpget.setConfig(config);
CloseableHttpResponse response = httpclient.execute(target, httpget);
try {
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
Or, for projects that use OkHttp:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import okhttp3.OkHttpClient;
import okhttp3.Authenticator;
import okhttp3.Credentials;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.Route;
public class FixieExample
{
public static void main(String[] args) throws Exception {
String fixieUrl = System.getenv("FIXIE_URL");
String[] fixieValues = fixieUrl.split("[/(:\\/@)/]+");
String fixieUser = fixieValues[1];
String fixiePassword = fixieValues[2];
String fixieHost = fixieValues[3];
int fixiePort = Integer.parseInt(fixieValues[4]);
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
Authenticator proxyAuthenticator = new Authenticator() {
@Override public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic(fixieUser, fixiePassword);
return response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build();
}
};
clientBuilder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(fixieHost, fixiePort)))
.proxyAuthenticator(proxyAuthenticator);
OkHttpClient client = clientBuilder.build();
Request request = new Request.Builder().url("http://www.example.com").build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
}
}
Using with Go
These examples assume the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
To use Fixie for specific http requests, you can create a custom http.Client:
package main
import (
"net/url"
"net/http"
"os"
"io/ioutil"
)
func main () {
fixieUrl, err := url.Parse(os.Getenv("FIXIE_URL"))
customClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(fixieUrl)}}
resp, err := customClient.Get("http://welcome.usefixie.com")
if (err != nil) {
println(err.Error())
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
println(string(body))
}
If you intend to use Fixie for all outbound requests, an alternative is to use the HTTP_PROXY
and HTTPS_PROXY
environment variables. Go honors these environment variables by default. You can set HTTP_PROXY
and HTTPS_PROXY
in your application, typically in main.go:
package main
import (
"net/http"
"os"
"io/ioutil"
)
func main () {
os.Setenv("HTTP_PROXY", os.Getenv("FIXIE_URL"))
os.Setenv("HTTPS_PROXY", os.Getenv("FIXIE_URL"))
resp, err := http.Get("http://welcome.usefixie.com")
if (err != nil) {
println(err.Error())
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
println(string(body))
}
Using with PHP
These examples assume the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
PHP cURL is the easiest way to get your PHP application working correctly with Fixie. Here’s how:
<?php
function proxyRequest() {
$fixieUrl = getenv("FIXIE_URL");
$parsedFixieUrl = parse_url($fixieUrl);
$proxy = $parsedFixieUrl['host'].":".$parsedFixieUrl['port'];
$proxyAuth = $parsedFixieUrl['user'].":".$parsedFixieUrl['pass'];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyAuth);
curl_close($ch);
}
$response = proxyRequest();
print_r($response);
?>
Using with .NET
HttpWebRequest myWebRequest=(HttpWebRequest)WebRequest.Create("https://www.example.com");
WebProxy fixie=new WebProxy();
fixie.Address=new Uri(FIXIE_ADDRESS);
fixie.Credentials=new NetworkCredential("fixie",FIXIE_TOKEN);
myWebRequest.Proxy=fixie;
See Microsoft’s documentation for more information.
Using with other languages
The FIXIE_URL
environment variable is a standard proxy URL that can be used by request libraries in any language. You can also use Fixie directly in cURL and other command-line tools:
curl http://welcome.usefixie.com --proxy $FIXIE_URL
This example assumes the FIXIE_URL
environment variable is set. For instructions on setting this variable on your local machine, see the Local Setup section.
End-to-end encryption of HTTPS requests
When your application makes a request to an HTTPS resource via Fixie, your application sends a CONNECT
request to Fixie. This request instructs Fixie to open a TCP connection to the remote host. Once this connection has been established, Fixie transparently tunnels this connection. Neither Fixie nor any other party has the ability to decrypt this traffic. The proxy negotiation (the initial CONNECT
request to Fixie) happens in the clear, but the connection with the remote host remains encrypted end-to-end.
For more information, see Wikipedia’s article on HTTP tunnels
Migrating between plans
Use the heroku addons:upgrade
command to migrate to a new plan.
$ heroku addons:upgrade fixie:newplan
-----> Upgrading fixie:newplan to sharp-mountain-4005... done, v18 ($49/mo)
Your plan has been updated to: fixie:newplan
Removing the add-on
Fixie can be removed via the CLI.
This will destroy all associated data and cannot be undone!
$ heroku addons:remove fixie
-----> Removing fixie from sharp-mountain-4005... done, v20 (free)
Connecting through a single IP address
By default, Fixie provides a load-balance pair of IP addresses. This allows us to provide very high (>99.99%) availability by load balancing across two availability zones.
If you have an external dependency that can only whitelist a single IP address, you can connect to a single IP in the cluster. To do this, replace the proxy group URL with either of the proxy IP addresses. So instead of http://fixie:abcd1234@pannier.usefixie.com:80
, connect to http://fixie:abcd1234@54.173.229.123:80
.
Connecting to a single IP address theoretically comes at some cost of availability, but in practice, this is tolerable for most applications.
Support
All Fixie support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is welcome at team@usefixie.com.