Show nav
Heroku Dev Center
  • Get Started
  • Docs
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Rails Support
      • Working with Bundler
    • Python
      • Working with Django
      • Background Jobs in Python
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with the Play Framework
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
    • Single Sign-on (SSO)
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Add-ons
  • ›
  • All Add-ons
  • ›
  • Fixie Socks
Fixie Socks

This add-on is operated by Fixie

Static IP addresses for database requests and other TCP connections

Fixie Socks

Last updated 15 June 2019

Table of Contents

  • The difference between Fixie Socks and Fixie
  • Provisioning the add-on
  • Local setup
  • Using with Node.js
  • Using with Go
  • Using with Java
  • Curl via Fixie Socks
  • SSH and SCP via Fixie Socks
  • FTP via Fixie Socks
  • Using with languages that don’t support SOCKS proxies
  • Dashboard
  • Removing the add-on
  • Support

Fixie Socks is a Heroku add-on that enables users to make TCP connections from a known IP address via a SOCKS proxy. Common use cases are database connections, FTP, SCP, and SSH. By connecting via Fixie Socks, users can integrate with external services and databases that do IP whitelisting. Fixie Socks is language- and framework-agnostic.

Fixie Socks acts as a SOCKS V5 proxy for outbound traffic, tunneling your requests through a known IP address. Each Fixie subscriber is assigned a set of static IP addresses. Through this proxy, subscribers can connect to any database or service that requires a fixed IP range.

Fixie Socks provides customers with a standard SOCKS V5 proxy URL that can be used to establish connections from any server-side language, including Node, Java, and Go. Fixie Socks can also be used by SSH, SCP, cURL, and other command-line tools.

The difference between Fixie Socks and Fixie

Fixie Socks provides a fixed set of IP addresses via a SOCKS V5 proxy. As such, Fixie Socks is capable of proxying any TCP connection. You can make HTTP and HTTPS requests via Fixie Socks, but Fixie (an HTTP proxy) is generally a better fit for that use case. Fixie Socks is perfect for making requests to databases, FTP servers, and other lower-level connections because it allows you to tunnel arbitrary TCP connections.

Provisioning the add-on

Fixie Socks can be attached to a Heroku application via the CLI:

A list of all plans available can be found here.

$ heroku addons:create fixie-socks
-----> Adding fixie-socks to sharp-mountain-4005... done, v18 (free)

After you provision Fixie Socks, a FIXIE_SOCKS_HOST config var is available in your app’s configuration. This contains the SOCKSV5 proxy URL through which your application makes outbound requests. This can be confirmed using the heroku config:get command:

$ heroku config:get FIXIE_SOCKS_HOST
user:pass@criterium.usefixie.com:1080

After installing Fixie Socks, the application should be configured to fully integrate with the add-on.

Local setup

Environment setup

For local development, it is necessary to replicate the FIXIE_SOCKS_HOST environment variable.

FIXIE_SOCKS_HOST can be retrieved either from the Fixie Socks dashboard or via the Heroku CLI:

$ heroku config:get FIXIE_SOCKS_HOST -s  >> .env

Credentials and other sensitive configuration values should not be committed to source-control. In Git, exclude the .env file with: echo .env >> .gitignore.

For more information, see the Heroku Local article.

Using with Node.js

With Node.js, the general pattern is to establish a SOCKS connection using a client library like socksjs and then provide this stream to the database driver, request library, or other library of your choosing.

Connecting to MySQL via Fixie Socks with Node.js

MySql2 connects via a SOCKS connection provided as the stream property. Because Fixie Socks terminates idle connections after 60 seconds of inactivity, we suggest using connection pooling (this is a best practice regardless) or manual error handling. The example below uses connection pooling:

'use strict';

const SocksConnection = require('socksjs');
const mysql = require('mysql2');
const fixieUrl = process.env.FIXIE_SOCKS_HOST;
const fixieValues = fixieUrl.split(new RegExp('[/(:\\/@)/]+'));

const mysqlServer = {
  host: 'your-host.example.com',
  port: 3306
};

const dbUser = 'user';
const dbPassword = 'password';
const db = 'database';

const fixieConnection = new SocksConnection(mysqlServer, {
  user: fixieValues[0],
  pass: fixieValues[1],
  host: fixieValues[2],
  port: fixieValues[3],
});

const mysqlConnPool = mysql.createPool({
  user: dbUser,
  password: dbPassword,
  database: db,
  stream: fixieConnection
});

mysqlConnPool.getConnection(function gotConnection(err, connection) {

  if (err) throw err;

  queryVersion(connection);
});

function queryVersion(connection) {
  connection.query('SELECT version();', function (err, rows, fields) {

      if (err) throw err;

      console.log('MySQL/MariaDB version: ', rows);
      connection.release();
      process.exit();
  });
}

Connecting to Postgres or Amazon Redshift via Fixie Socks with Node.js

As with mysql, you can pass a custom stream to the node-postgres library. This will work both for connections to Postgres databases as well as to Amazon Redshift:

'use strict';

const pg = require('pg');
const SocksConnection = require('socksjs');

const fixieUrl = process.env.FIXIE_SOCKS_HOST;
const fixieValues = fixieUrl.split(new RegExp('[/(:\\/@)/]+'));

const pgServer = {
  host: 'YOUR-HOST',
  port: 5432
};

const fixieConnection = new SocksConnection(pgServer, {
  user: fixieValues[0],
  pass: fixieValues[1],
  host: fixieValues[2],
  port: fixieValues[3],
});

const connectionConfig = {
  user: 'YOUR-DB-USERNAME',
  password: 'YOUR-DB-PASSWORD',
  database: 'YOUR-DATABASE',
  stream: fixieConnection,
  ssl: true // Optional, depending on db config
};

var client = new pg.Client(connectionConfig);

client.connect(function (err) {
  if (err) throw err;
  client.query('SELECT 1+1 as test1', function (err, result) {
    if (err) throw err;
    console.log(result.rows[0]);
    client.end(function (err) {
      if (err) throw err;
    });
  });
});

Establishing an SSH connection over Fixie Socks with Node.js

The SSH2 library can be used to establish an SSH connection and execute commands over Fixie Socks.

var socks = require('socksv5'),
    SSHClient = require('ssh2').Client;

const fixieUrl = process.env.FIXIE_SOCKS_HOST;
const fixieValues = fixieUrl.split(new RegExp('[/(:\\/@)/]+'));

socks.connect({
  host: 'ssh.example.org',
  port: 22,
  proxyHost: fixieValues[2],
  proxyPort: fixieValues[3],
  auths: [socks.auth.UserPassword(fixieValues[0], fixieValues[1])]
}, function(socket) {
  var conn = new SSHClient();
  conn.on('ready', function() {
    conn.exec('uptime', function(err, stream) {
      if (err) throw err;
      stream.on('close', function(code, signal) {
      conn.end();
      }).on('data', function(data) {
        console.log('STDOUT: ' + data);
      }).stderr.on('data', function(data) {
        console.log('STDERR: ' + data);
      });
    });
  }).connect({
    sock: socket,
    username: 'ssh-user',
    privateKey: require('fs').readFileSync('/here/is/my/key')
  });
});

Making HTTP or HTTPS requests over Fixie Socks with Node.js

The socks package provides an agent that can be used by the Node’s http and https libraries, as well as by popular higher-level libraries like request.

'use strict';

const http = require('http');
const Socks = require('socks');

const fixieUrl = process.env.FIXIE_SOCKS_HOST;
const fixieValues = fixieUrl.split(new RegExp('[/(:\\/@)/]+'));

const socksAgent = new Socks.Agent({
    proxy: {
        ipaddress: fixieValues[2],
        port: fixieValues[3],
        type: 5,
        authentication: {
            username: fixieValues[0],
            password: fixieValues[1]
        }
    }},
    true, // true HTTPS server, false for HTTP server
    false // rejectUnauthorized option passed to tls.connect()
);

function resHandler(res) {
  let responseBody = '';
  res.on('data', (chunk) => {
    responseBody += chunk;
  });
  res.on('error', () => {
    process.exit(1);
  });
  res.on('end', () => {
    console.log(responseBody);
    socksAgent.encryptedSocket.end();
  });
}


http.get({ hostname: 'example.com', port: '443', agent: socksAgent}, resHandler);

Using with Go

Golang’s net/proxy package provides a Socks5 proxy dialer that can be used with Fixie Socks. This dialer can be used for any TCP connection. The example below uses this to make an HTTP request:

package main

import (
  "fmt"
  "io/ioutil"
  "net/http"
  "os"
  "strings"
  "golang.org/x/net/proxy"
)

const URL = "http://www.example.com"

func main() {
  fixie_data := strings.Split(os.Getenv("FIXIE_SOCKS_HOST"), "@")
  fixie_addr := fixie_data[1]
  auth_data := strings.Split(fixie_data[0], ":")
  auth := proxy.Auth{
    User: auth_data[0],
    Password: auth_data[1],
  }

  dialer, err := proxy.SOCKS5("tcp", fixie_addr, &auth, proxy.Direct)
  if err != nil {
    fmt.Fprintln(os.Stderr, "can't connect to the proxy:", err)
    os.Exit(1)
  }
  httpTransport := &http.Transport{}
  httpClient := &http.Client{Transport: httpTransport}

  httpTransport.Dial = dialer.Dial

  req, err := http.NewRequest("GET", URL, nil)
  if err != nil {
    fmt.Fprintln(os.Stderr, "can't create request:", err)
    os.Exit(2)
  }
  resp, err := httpClient.Do(req)
  if err != nil {
    fmt.Fprintln(os.Stderr, "can't GET page:", err)
    os.Exit(3)
  }
  defer resp.Body.Close()
  b, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    fmt.Fprintln(os.Stderr, "error reading body:", err)
    os.Exit(4)
  }
  fmt.Println(string(b))
}

Using with Java

Java supports a system property socksProxyHost, which can be used to route every outbound request through Fixie Socks. Additionally, Java 7 introduced ProxySelector, which can be used to conditionally proxy requests depending on the hostname.

A simple example that proxies all outbound requests through Fixie Socks:

URL fixie = new URL(System.getenv("FIXIE_SOCKS_HOST"));
String[] fixieUserInfo = fixie.getUserInfo().split(':');
String fixieUser = fixieUserInfo[0];
String fixiePassword = fixieUserInfo[1];
System.setProperty("socksProxyHost", fixie.getHost());
Authenticator.setDefault(new ProxyAuthenticator(fixieUser, fixiePassword));

//...

private class ProxyAuthenticator extends Authenticator {
  private final PasswordAuthentication passwordAuthentication;
  private ProxyAuthenticator(String user, String password) {
    passwordAuthentication = new PasswordAuthentication(user, password.toCharArray());
  }

  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return passwordAuthentication;
  }
}

Curl via Fixie Socks

Curl accepts a socks5 argument:

curl --socks5 $FIXIE_SOCKS_HOST http://example.com

SSH and SCP via Fixie Socks

SSH and SCP accept a ProxyCommand option. Using this option, you can pass in an ncat command that establishes a connection via the Fixie Socks proxy. This requires ncat v7 or newer.

Ncat does not accept proxy authentication via the standard proxy url schema, so instead you must provide it as a separate argument:

ssh -o ProxyCommand='ncat --proxy-type socks5 --proxy YOUR-FIXIE-DOMAIN.usefixie.com:1080 --proxy-auth fixie:YOUR-FIXIE-TOKEN %h %p' serveruser@server.ip.address

FTP via Fixie Socks

Making FTP requests via Fixie Socks is straight forward, but depending on the configuration of the FTP server, you may need to specify a specific Fixie IP address instead of using your load-balanced Fixie Socks proxy URL.

FTP uses multiple TCP connections (a control connection and a transfer connection). If your FTP server supports “passive promiscuous” connections, connecting through the standard Fixie Socks URL works without issue. If, however, the server does not support “passive promiscuous” connections, both the control and transfer connection must go through the same IP. For this use case, you can proxy directly through a specific Fixie Socks IP instead of through a load-balanced Fixie Socks proxy group. You can find the IP address and credentials in the Fixie Socks dashboard.

An example using cURL:

curl -v 'ftp://ftp2.census.gov/robots.txt' --socks5-hostname $FIXIE_SOCKS_IP_SPECIFIC_URL

cURL versions prior 7.48 had a bug which left the SOCKS connection open after the FTP transfer completed. We recommend using cURL 7.48 or later.

Using with languages that don’t support SOCKS proxies

Some languages do not provide native support for SOCKS proxies. Where this is the case, there are other options for using Fixie Socks.

  • There are several utilities that transparently proxy requests over SOCKS5 proxies like Fixie Socks. Popular options include Dante Socksify client, tsocks, and proxychains. Each of these utilities require some caveats: Dante only works on linux, so is not a good option if you develop locally on Mac or Windows. tsocks is not threadsafe, so is not a good choice for some applications. proxychains requires a numeric IPV4 address rather than a host name - you can provide one from your Fixie Dashboard, but in doing so you lose the availability benefits of Fixie’s load-balanced SOCKS proxy cluster.
  • Alternately, socat can be used to establish port-forwarding through Fixie Socks. Socat will establish a tunnel through Fixie Socks and bind to a local port through which your service can make requests.

Dashboard

The Fixie Socks dashboard allows you to view your connection logs and account settings.

The dashboard can be accessed via the CLI:

$ heroku addons:open fixie-socks
Opening fixie-socks for sharp-mountain-4005

or by visiting the Heroku Dashboard and selecting the application in question. Select Fixie Socks from the add-ons menu.

Removing the add-on

Fixie Socks can be removed via the CLI.

This will destroy all associated data and cannot be undone! If your application is configured to make requests through Fixie Socks, those requests will fail after removing the add-on.

$ heroku addons:destroy fixie-socks
-----> Removing fixie-socks from sharp-mountain-4005... done, v20 (free)

Support

All Fixie Socks support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is welcome via email at team@usefixie.com.

Keep reading

  • All Add-ons
  • Running Apps Locally
  • Support Channels

Feedback

Log in to submit feedback.

FixieFlightFormation

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies