Fork me on GitHub



What is SSF?

Secure Socket Funneling (SSF) is a network tool and toolkit.
It provides simple and efficient ways to forward data from multiple sockets (TCP or UDP) through a single secure TLS link to a remote computer.

Motivations

The initial aim of SSF was to provide an easy way for users and developers to multiplex and demultiplex various network data flows. It was designed to:

  • be cross platform
  • be lightweight (preferably standalone)
  • be easily extensible
  • provide modern (TLS 1.2) secure point-to-point communication with the strongest cipher-suites
  • provide high performance communications using the benefits of modern multi-core / multi-threaded architecture

These requirements excluded SSH which showed limitations on all items (particularly in performance, but also by the lack of server side application on Windows). Classic VPN software was also excluded because the requirement of administrator rights was too limiting.

Specific features

  • One feature which was not present in any another equivalent network tool was UDP forwarding. UDP is nonetheless widely used in real-time services (VoIP, online gaming, ...) and for DNS. Therefore, SSF is able to forward both TCP and UDP from the client to the server (options -L and -U) as well as from the server to the client (options -R and -V)

  • SSF also allows dynamic port forwarding with a SOCKS server from the client to the server (option -D just like SSH) and from the server to the client (option -F which SSH does not allow)

  • Basic shell support on Windows (cmd or Powershell), Linux and OS X. This feature must be activated on client or server prior to use. This is the first draft and we plan to improve it over time. Feel free to contribute!

  • The bouncing feature simply allows to forward the traffic from one point to another, through a list of intermediary relay servers

DevOps friendly

SSF command-line was designed as a drop-in replacement for SSH (on equivalent features, such as port forwarding or SOCKS), so that you can benefit of the performance and security gain with minimal - or even, not a single - update for your scripts and tools.

How to configure SSF

SSF provides a simple way to route an SSF connection between a client and a server through a list of SSF relay servers without protocol or cryptographic overhead. At this point, the traffic is decrypted as it is received by a relay and re-encrypted to be sent to the next relay or final destination. This means that the data will be encrypted between each relay but will transit unencrypted on the relay itself. It is therefore essential that the relay servers be secure and controlled by the owner of the data.

If users were to express the need, future versions could add a second cryptographic layer between the client and the destination server so that the data remained encrypted by this layer on every relay.

Required files

With default options, the following files and folders should be in the directory of execution of a client or a server (see the Security features section if you do not know how to generate them):

  • ./certs/dh4096.pem
  • ./certs/certificate.crt
  • ./certs/private.key
  • ./certs/trusted/ca.crt

Where :

  • dh4096.pem contains the Diffie-Hellman parameters needed for the establishment of session keys
  • certificate.crt and private.key are the certificate and the private key of the SSF server or client
  • ca.crt is the concatenated list of root certificates trusted by the SSF server or client
The certificate and the private key should be unique to each SSF client or server.

Moreover, a client will be able to connect to a server if two conditions are fulfilled:

  • One of the certification authority which signed the server certificate is present in the trusted list of the client
  • One of the certification authority which signed the client certificate is present in the trusted list of the server

In order to customize the paths and file names, the command line accepts a configuration file option -c.
An example is given below.

Configuration file

The configuration file is JSON format file in which several options can be specified. At this point, only security options relative to TLS use can be customized. See below an example of configuration file. For more information about TLS and SSF security see the Security features section.

{
  "ssf": {
    "tls" : {
      "ca_cert_path": "./certs/trusted/ca.crt",
      "cert_path": "./certs/certificate.crt",
      "key_path": "./certs/private.key",
      "key_password": "",
      "dh_path": "./certs/dh4096.pem",
      "cipher_alg": "DHE-RSA-AES256-GCM-SHA384"
    },
    "http_proxy" : {
      "host": "",
      "port": "",
      "credentials": {
        "username": "",
        "password": "",
        "domain": "",
        "reuse_ntlm": "true",
        "reuse_nego": "true"
      }
    },
    "services": {
      "datagram_forwarder": { "enable": true },
      "datagram_listener": {
        "enable": true,
        "gateway_ports": false
      },
      "stream_forwarder": { "enable": true },
      "stream_listener": {
        "enable": true,
        "gateway_ports": false
      },
      "file_copy": { "enable": false },
      "shell": {
        "enable": false,
        "path": "/bin/bash|C:\\windows\\system32\\cmd.exe",
        "args": ""
      },
      "socks": { "enable": true }
    }
  }
}
tls.ca_cert_path
relative or absolute path to the CA certificate file
tls.cert_path
relative or absolute path to the instance certificate file
tls.key_path
relative or absolute path to the private key file
tls.key_password
the password protecting the private key (if any)
tls.dh_path
relative or absolute path to the Diffie-Hellman file
tls.cipher_alg
List of allowed SSL cipher suite (see OpenSSL documentation for more information)
http_proxy.host
HTTP proxy host
http_proxy.port
HTTP proxy port
http_proxy.credentials.username
proxy username credentials
http_proxy.credentials.password
proxy password credentials
http_proxy.credentials.domain
user domain (NTLM and Negotiate auth on Windows only)
http_proxy.credentials.reuse_ntlm
reuse current computer user credentials to authenticate with proxy NTLM auth (SSO)
http_proxy.credentials.reuse_kerb
reuse current computer user credentials (Kerberos ticket) to authenticate with proxy Negotiate auth (SSO)
services.*.enable
enable/disable local microservice
services.*.gateway_ports
enable/disable gateway ports
services.shell.path
binary path used for process creation
services.shell.args
binary arguments used for process creation

For an SSF server, if the private key is encrypted but no password was provided with the configuration file, all connections will fail.
However, for an SSF client, a password prompt will be presented to the user. It will give him the opportunity to enter the password, if needed.

Microservices

SSF is using microservices to build its features (TCP forwarding, remote SOCKS, ...) There are 7 microservices:

  • stream_forwarder
  • stream_listener
  • datagram_forwarder
  • datagram_listener
  • file_copy
  • socks
  • shell
Each feature is the combination of at least one client side microservice and one server side microservice.
This table sums up how each feature is assembled:

ssfc feature microservice client side microservice server side
-L: TCP forwarding stream_listener stream_forwarder
-R: remote TCP forwarding stream_forwarder stream_listener
-U: UDP forwarding datagram_listener datagram_forwarder
-V: remote UDP forwarding datagram_forwarder datagram_listener
-D: SOCKS stream_listener socks
-F: remote SOCKS socks stream_listener
-X: shell stream_listener shell
-Y: remote shell shell stream_listener

This architecture makes it easier to build remote features: they use the same microservices but on the opposite side.
ssfc and ssfs come with pre-enabled microservices. Here is the default microservices configuration:

"ssf": {
  "services": {
    "datagram_forwarder": { "enable": true },
    "datagram_listener": { "enable": true },
    "stream_forwarder": { "enable": true },
    "stream_listener": { "enable": true },
    "socks": { "enable": true },
    "file_copy": { "enable": false },
    "shell": { "enable": false }
  }
}

To enable or disable a microservice, set its enable option to true or false.
Trying to use a feature requiring a disabled microservice will result in an error message.

How to use the command line

Standard command line options

Client command line

ssfc[.exe] [options] host

Basic options:
  -h [ --help ]                         Produce help message
  -v [ --verbosity ] level (=info)      Verbosity:
                                          critical|error|warning|info|debug|trace
  -q [ --quiet ]                        Do not display log

Local options:
  -c [ --config ] config_file_path      Set config file. If option empty, try to load 'config.json' file from working
                                        directory
  -b [ --circuit ] circuit_file_path    Set circuit file. If option empty, try to load 'circuit.txt' file from working
                                        directory
  -p [ --port ] port (=8011)            Set remote SSF server port
  -g [ --gateway-ports ]                Allow gateway ports. At connection, client will be allowed to specify
                                        listening network interface on every services
  -S [ --status ]                       Display microservices status (on/off)

Supported service commands:
  -Y [ --remote-shell ] [[rem_ip]:]rem_port
                                        Open a port server side, each connection to that port launches a
                                        shell client side with I/O forwarded from/to the socket (shell microservice
                                        must be enabled client side prior to use)
  -F [ --remote-socks ] [[rem_ip]:]rem_port
                                        Run a SOCKS proxy on localhost accessible from server [[rem_ip]:]rem_port
  -X [ --shell ] [[loc_ip]:]loc_port
                                        Open a port on the client side, each connection to that port launches a
                                        shell server side with I/O forwarded to/from the socket (shell microservice
                                        must be enabled server side prior to use)
  -D [ --socks ] [[loc_ip]:]loc_port
                                        Run a SOCKS proxy on remote host accessible from client [[loc_ip]:]loc_port
  -L [ --tcp-forward ] [[loc_ip]:]loc_port:dest_ip:dest_port
                                        Forward TCP client [[loc_ip]:]loc_port to dest_ip:dest_port from server
  -R [ --tcp-remote-forward ] [[rem_ip]:]rem_port:dest_ip:dest_port
                                        Forward TCP server [[rem_ip]:]rem_port to target dest_ip:dest_port from client
  -U [ --udp-forward ] [[loc_ip]:]loc_port:dest_ip:dest_port
                                        Forward UDP client [[loc_ip]:]loc_port to target dest_ip:dest_port from server
  -V [ --udp-remote-forward ] [[rem_ip]:]rem_port:dest_ip:dest_port
                                        Forward UDP server [[rem_ip]:]rem_port to dest_ip:dest_port from client

Server command line

ssfs[.exe] [options] [host]

Basic options:
  -h [ --help ]                         Produce help message
  -v [ --verbosity ] level (=info)      Verbosity:
                                          critical|error|warning|info|debug|trace
  -q [ --quiet ]                        Do not display log

Local options:
  -c [ --config ] config_file_path      Set config file. If option empty, try to load 'config.json' file from working
                                        directory
  -p [ --port ] port (=8011)            Set local SSF server port
  -R [ --relay-only ]                   Server will only relay connections
  -g [ --gateway-ports ]                Allow gateway ports. At connection, client will be allowed to specify listening
                                        network interface on every services
  -S [ --status ]                       Display microservices status (on/off)

Examples

For instance, this command line will start SSF as a server on default port 8011:

./ssfs

And this command will connect SSF client to the server listening on localhost and port 8011 and start a SOCKS server listening on port 10000 of the client side:

./ssfc -D 10000 127.0.0.1

Copy command line options

ssfcp[.exe] [options] [host@]/absolute/path/file [[host@]/absolute/path/file]

Basic options:
  -h [ --help ]                       Produce help message
  -v [ --verbosity ] level (=info)    Verbosity:
                                        critical|error|warning|info|debug|trace
  -q [ --quiet ]                      Do not display log

Local options:
  -c [ --config ] config_file_path    Set config file. If option empty, try to load 'config.json' file from working
                                      directory
  -b [ --circuit ] circuit_file_path  Set circuit file. If option empty, try to load 'circuit.txt' file from working
                                      directory
  -p [ --port ] port (=8011)          Set remote SSF server port

Copy options:
  -t [ --stdin ]                      Input will be stdin
-b
bounce_file is the file containing the list of relays to use
-c
config_file is the file containing configuration for SSF (TLS configuration)
-t
input data from stdin

Examples

Copy local files to remote directory

This command will copy the file /tmp/test.txt in the remote directory D:\test of server 10.0.0.1

ssfcp /tmp/test.txt 10.0.0.1@D:\\test

This command will copy all local files matching the pattern /tmp/test*.txt in the remote directory D:\test of 10.0.0.1

ssfcp /tmp/test*.txt 10.0.0.1@D:\\test

Copy client stdin into remote file

This command will pipe the resulting archive into the file D:\test\test.tar of 10.0.0.1

tar cf - /tmp/test | ssfcp -t 10.0.0.1@D:\\test\\test.tar

Copy remote files to local directory

This command will copy the file D:\test\test.txt of 10.0.0.1 into the local directory /tmp

ssfcp 10.0.0.1@D:\\test\\test.txt /tmp

This command will copy all files of 10.0.0.1 matching D:\test\test*.txt into the local directory /tmp

ssfcp 10.0.0.1@D:\\test\\test*.txt /tmp

How to use the relay servers (the bouncing feature)

SSF provides a simple way to route an SSF connection between a client and a server through a list of SSF relay servers without protocol or cryptographic overhead. At this point, the traffic is decrypted as it is received by a relay and re-encrypted to be sent to the next relay or final destination.

New 2.1.0
A second cryptographic layer between the client and the destination server is added.



The bounce file

In order to route an SSF client connection through a list of relay servers, the option -b must be added to the command line to specify the bounce file. This file must contain one relay server per line: IP address or domain name and port on which SSF is listening. For instance:

SERVER1:PORT1
SERVER2:PORT2
SERVER3:PORT3

For the file above, the relay chain will be CLIENT <-> SERVER1:PORT1 <-> SERVER2:PORT2 <-> SERVER3:PORT3 <-> DESTINATION

Example

In this example, a client located in the 10.0.1.* subnet wants to connect to the SSF server on 10.0.6.1:5000. However for this example, firewalls will only allow each subnet to communicate with the next one through a single address. For instance, in a subnet A.B.C.*, only A.B.C.1 can communicate with A.B.C-1.* and A.B.C+1.*. Therefore, to reach 10.0.6.1, the client has to go through 10.0.1.1, 10.0.2.1, ... and 10.0.6.1.

  • It is expected that an SSF server is running on each of the six addresses on port 5000 using a command line similar to:
    ./ssfs -p 5000
  • Use the following bounce.txt file:
    10.0.1.1:5000
    10.0.2.1:5000
    10.0.3.1:5000
    10.0.4.1:5000
    10.0.5.1:5000
  • Connect the SSF client to 10.0.6.1:5000 through all the relay servers using the following command line:
    ./ssfc -b bounce.txt -p 5000 10.0.6.1

How to use the SOCKS feature

Local SOCKS

The SSF Client -D port option opens the given port on the SSF Client machine and forward SOCKS requests to the target SSF Server.
The SSF Server will act as the SOCKS server.



Remote SOCKS

The SSF Client -F port option opens the given port on the target SSF Server machine and forward SOCKS requests to the SSF Client.
The SSF Client will act as the SOCKS server.



Command line

No bounce feature

  • Launch SSF_SERVER on a port (10000 in this example)
    ./ssfs -p 10000
  • Connect SSF_CLIENT to SSF_SERVER, initialize a SOCKS server on SSF_SERVER side and open port 9000 on SSF_CLIENT side to communicate to SOCKS server
    ./ssfc -D 9000 -p 10000 127.0.0.1
    Use -F instead of -D to have the SOCKS server on SSF_CLIENT side and open the port 9000 on SSF_SERVER side

With bounce feature

  • Launch SSF_SERVER_1 on a port (10000 in this example)
    ./ssfs -p 10000
  • Launch SSF_SERVER_2 on a port (10001 in this example)
    ./ssfs -p 10001
  • Create the bounce file bounce.txt
    127.0.0.1:10000
    The client will connect to SSF_SERVER_2 with a bounce on SSF_SERVER_1
  • Connect SSF_CLIENT to SSF_SERVER_2 with one bounce, initialize a SOCKS server on SSF_SERVER_2 and open port 9000 on client side to communicate to SOCKS server
    ./ssfc -b bounce.txt -D 9000 -p 10001 127.0.0.1
    Use -F instead of -D to have the SOCKS server on SSF_CLIENT side and open the port 9000 on SSF_SERVER_2 side

How to use the TCP port forwarding feature

No bounce feature

  • Launch SSF_SERVER on a port (10000 in this example)
    ./ssfs -p 10000
  • Connect SSF_CLIENT to SSF_SERVER
    ./ssfc -L 9000:127.0.0.1:80 -p 10000 127.0.0.1
    Use -R instead of -L to forward to the SSF_CLIENT side and open the port 9000 on SSF_SERVER side

With bounce feature

  • Launch SSF_SERVER_1 on a port (10000 in this example)
    ./ssfs -p 10000
  • Launch SSF_SERVER_2 on a port (10001 in this example)
    ./ssfs -p 10001
  • Create the bounce file bounce.txt
    127.0.0.1:10000
    The SSF_CLIENT will connect to SSF_SERVER_2 with a bounce on SSF_SERVER_1
  • ./ssfc -b bounce.txt -L 9000:127.0.0.1:80 -p 10001 127.0.0.1
    Use -R instead of -L to forward to the SSF_CLIENT side and open the port 9000 on SSF_SERVER_2 side

How to use the UDP port forwarding feature

No bounce feature

  • Launch SSF_SERVER on a port (10000 in this example)
    ./ssfs -p 10000
  • Connect SSF_CLIENT to SSF_SERVER
    ./ssfc -U 9000:127.0.0.1:80 -p 10000 127.0.0.1
    Use -V instead of -U to forward to the SSF_CLIENT side and open the port 9000 on SSF_SERVER side

With bounce feature

  • Launch SSF_SERVER_1 on a port (10000 in this example)
    ./ssfs -p 10000
  • Launch SSF_SERVER_2 on a port (10001 in this example)
    ./ssfs -p 10001
  • Create the bounce file bounce.txt
    127.0.0.1:10000
    The SSF_CLIENT will connect to SSF_SERVER_2 with a bounce on SSF_SERVER_1
  • ./ssfc -b bounce.txt -U 9000:127.0.0.1:80 -p 10001 127.0.0.1
    Use -V instead of -U to forward to the SSF_CLIENT side and open the port 9000 on SSF_SERVER_2 side

How to use SSF shell

SSF provides basic shell support on Windows, Linux and OS X with -X and -Yoptions.
Default shell is cmd.exe on Windows and /bin/bash on Linux or OS X. The shell is fully configurable by modifying ssf.services.shell configuration file section (e.g. you can set Powershell as the default shell on Windows, see below).

The shell feature of SSF is quite different from SSH at the moment. Instead of having direct interaction with a shell instance, SSF shell option will open a listening TCP socket locally (-X) or instruct the server to open one remotely (-Y). Each connection to that socket will then launch a shell on the other side with its I/O forwarded.

Shell microservice must be enabled prior to use (configuration file)

{
    "ssf": {
        "services": {
            "shell": {
                "enable": true
            }
        }
    }
}
-X option will require the shell microservice to be enabled on the server
-Y option will require the shell microservice to be enabled on the client

This is the first draft and we plan to improve it over time. Actually, you may have some ideas to improve this feature so feel free to suggest or even implement them. We will be honored to review and accept pull requests.

Example

  • Launch server on ssf.example.com
    ./ssfs
  • Connect client to server
    ./ssfc -X 10000 -Y 11000 ssf.example.com
    -X: client opens a listening socket on the given port (10000). Each connection to that socket (using netcat for example) will launch a shell on the server side.
    -Y: client orders the server to open a listening socket on the given port (11000). Each connection to that socket (using netcat for example) will launch a shell on the client side.
    I/O are forwarded through the SSF tunnel from/to the shell instance.
  • You need to take into consideration some issues such as double echoing (both client and server display your input) or control command interpretation. We will provide a better way to handle this in a future version.
    Here are some workarounds according to your use case:
    • Interact with Linux or OS X shell: if you are using netcat in bash, you must change some options of the current terminal device with stty before establishing a connection:
      stty -echo -icanon -isig min 1
      -echo
      disable local echo
      -icanon
      disable canonical input
      -isig
      disable checking of special control characters (e.g. CTRL+C, CTRL+D)
      min 1
      read and process one character at a time
      All special interpretations will be done by the remote shell (TAB, CTRL+C, CTRL+D, etc.). After use, do not forget to reactivate terminal options device. Here is a oneliner:
      stty -echo -icanon -isig min 1; nc 127.0.0.1 10000; stty echo icanon isig;
    • Interact with Windows shell: if you are using netcat in bash, you can disable checking of control characters. Special characters sequence (TAB, UP, etc.) are disabled. We are still looking for a solution for setting the character input mode. Input will be processed one line at a time and you will notice double echoing.
      stty -isig; nc 127.0.0.1 10000; stty isig;
      If you are facing encoding issue (e.g. occidental accent), you may set your terminal encoding as Occidental (IBM850) on Ubuntu or Western (DOS Latin1) on OS X.

Set Powershell as the default shell on Windows

Here is a configuration file example for setting Powershell as the default shell on Windows platform:

{
    "ssf": {
        "services": {
            "shell": {
                "enable": true,
                "path": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
                "args": "-File -"
            }
        }
    }
}
ssf.services.shell.enable
true to activate local shell microservice
ssf.services.shell.path
Powershell binary path. Modify the path according to your system.
ssf.services.shell.args
Powershell binary arguments. -File - is required for redirecting SSF I/O to stdin/stdout Powershell process.

Login user at connection on Linux or OS X

Client or server must be run as superuser

login can be used to login user on connection. Here is an example for setting it instead of /bin/bash:

{
    "ssf": {
        "services": {
            "shell": {
                "enable": true,
                "path": "/bin/login"
            }
        }
    }
}
ssf.services.shell.path
Login binary path. Modify the path according to your system (e.g. /bin/login on Ubuntu/Debian, /usr/bin/login on OS X).

How to copy file

Command line

ssfcp[.exe] [-b bounce_file] [-c config_file] [-p port] [-t] [host@]path [[host@]path]
-b
bounce_file is the file containing the list of relays to use
-c
config_file is the file containing configuration for SSF (TLS configuration)
-p
port is the port of the remote SSF server
-t
input data from stdin

ssfcp is cross platform and its syntax is similar to scp command.
The main difference resides in the separator between host and path: @ for ssfcp instead of :

Since ssfcp is part of SSF framework, it is also fully compatible with the relay servers feature.

From Linux to Linux

Local to remote

This command will copy the file /home/doe/test.txt into the remote directory /tmp/test_dir of server 10.0.0.1

ssfcp /home/doe/test.txt 10.0.0.1@/tmp/test_dir

Local globbing to remote

This command will copy all local files matching /home/doe/*.txt into the remote directory /tmp/test_dir of server 10.0.0.1

ssfcp /home/doe/*.txt 10.0.0.1@/tmp/test_dir

stdin to remote

This command will send the tar archive of /tmp/test through client stdin into the remote file /tmp/test_dir/test.tar of server 10.0.0.1

tar cf - /tmp/test | ssfcp 10.0.0.1@/tmp/test_dir/test.tar

Remote to local

This command will copy the remote file /home/doe/test.txt of 10.0.0.1 into the local directory /tmp/test_dir

ssfcp 10.0.0.1@/home/doe/test.txt /tmp/test_dir

From Windows to Linux

Local to remote

This command will copy the file D:\test.txt into the remote directory /tmp/test_dir of server 10.0.0.1

ssfcp.exe D:\\test.txt 10.0.0.1@/tmp/test_dir

Local globbing to remote

This command will copy all local files matching D:\*.txt into the remote directory /tmp/test_dir of server 10.0.0.1

ssfcp.exe D:\\test.txt 10.0.0.1@/tmp/test_dir

stdin to remote

This command will send the tar archive of D:\test through client stdin into the remote file /tmp/test_dir/test.tar of server 10.0.0.1

tar.exe cf - D:\\test | ssfcp.exe 10.0.0.1@/tmp/test_dir/test.tar

Remote to local

This command will copy the remote file D:\test.txt of 10.0.0.1 into the local directory /tmp/test_dir

ssfcp 10.0.0.1@D:\\test.txt /tmp/test_dir

From Windows to Windows

Local to remote

This command will copy the file D:\test.txt into the remote directory E:\test_dir of server 10.0.0.1

ssfcp.exe D:\\test.txt 10.0.0.1@E:\\test_dir

Local globbing to remote

This command will copy all local files matching D:\*.txt into the remote directory E:\test_dir of server 10.0.0.1

ssfcp.exe D:\\*.txt 10.0.0.1@E:\\test_dir

stdin to remote

This command will send the tar archive of D:\test through client stdin into the remote file E:\test_dir\test.tar of server 10.0.0.1

tar.exe cf - D:\\test | ssfcp.exe 10.0.0.1@E:\\test_dir\\test.tar

Remote to local

This command will copy the remote file D:\test.txt of 10.0.0.1 into the local directory E:\test_dir

ssfcp.exe 10.0.0.1@D:\\test.txt E:\\test_dir

How to browse the web securely and privately from everywhere

You are in a coffee shop or an hotel

and you are connected to its wifi network. You do not trust this connection or don't want the hotel's proxy / router or guy next to you to know what web page you visit.

You will need two things:

  • the server side: running, connected to Internet (for example, your home machine, running Windows, or Linux, or Mac)
  • the client side: running on your laptop when you want to browse Internet while being locally connected to an untrusted network (e.g. public wifi networks)



Configuring the server side (e.g. your home machine, up and running, connected to internet, even when you are not at home)

./ssfs -p port 10000

Now, your home server is listening on port 10000, and is waiting for an authenticated client. For this example, let's say that the public IP address of your server is "SERVER_IP"

Configuring the client side (e.g. your laptop): the simple way

./ssfc -D 9000 -p 10000 SERVER_IP

Simply run this command, and configure your browser (firefox, IE, Chrome, Safari...), to use a socks server on address 127.0.0.1 port 9000

This command uses -D (server side socks resolution) option.

Advanced : Secure DNS resolution

./ssfc -D 9000 -U 53:208.67.222.222:53 -p 10000 SERVER_IP

Someone in the wifi network could fake DNS resolution, and redirect you to malicious websites.

Change your DNS interface settings to 127.0.0.1, and, thanks to this command, every DNS request will go througt the secure SSF funnel, and public OpenDNS DNS server (208.67.222.222) will resolve them.
No DNS request will leak on the network (wifi) you're connected to, and from DNS server view (OpenDNS provider for this example), it's your Server (SERVER_IP) that is making the DNS request.

This command combines both -D (server side socks) and -U (UDP forward) options. OpenDNS DNS server is given as an example. You could use any DNS server

Coffee shop firewall restrictions

Sometimes, public Wifi uses firewall restrictions to allow only web-related outgoing port (generaly 80-http, or 443-https).

To comply with these restrictions and be able to browse securely using SSF, you should setup the SSF server to listen on port 80 or 443 (instead of 10000 in the basic example)

Binding SSF on a port below 1024 (e.g. 53, 80 or 443) will require administrative privileges. But as long as the SSF run on a machine that you control, this should not be an issue.

How to build on Windows

Requirements

  • Winrar >= 5.2.1
  • Boost >= 1.61.0
  • OpenSSL >= 1.0.2
  • Google Test = 1.7.0
  • CMake >= 2.8.11
  • nasm (required by OpenSSL build)
  • Active Perl >= 5.20 (required by OpenSSL build)
  • C++11 compiler (Visual Studio 2013, Clang, g++, etc.)

SSF_SECURITY

  • STANDARD: the project will be build with standard security features
  • FORCE_TCP_ONLY: the project will be built without security features to facilitate debugging

Process

  • Go in project directory
    cd PROJECT_PATH
  • Copy Boost archive in third_party/boost
    cp boost_1_XX_Y.tar.bz2 PROJECT_PATH/third_party/boost
  • Copy OpenSSL archive in third_party/openssl
    cp openssl-1.0.XY.tar.gz PROJECT_PATH/third_party/openssl
  • Copy GTest archive in third_party/gtest
    cp gtest-1.X.Y.zip PROJECT_PATH/third_party/gtest
  • Generate project
    git submodule update --init --recursive
    mkdir PROJECT_PATH/build
    cd PROJECT_PATH/build
    
    • Visual Studio 2013: 32 bits
      cmake .. -G "Visual Studio 12 2013" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
    • Visual Studio 2013: 64 bits
      cmake .. -G "Visual Studio 12 2013 Win64" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
    • Visual Studio 2015: 32 bits
      cmake .. -G "Visual Studio 14 2015" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
    • Visual Studio 2015: 64 bits
      cmake .. -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
  • Build project
    cd PROJECT_PATH/build
    cmake --build . --config Release -- -MaxCpuCount

Known issues

  • Boost build system needs to be patched to comply with our project (extra flags for Win32 binaries). Follow instructions in third_party/boost/README.md
  • GTest archive content has changed since its repository is on Github. Follow instructions in third_party/gtest/README.md to fix the build system
  • If you are using openssl-1.0.2a, you need to fix the file crypto/x509v3/v3_scts.c. It contains an incorrect #include line.
    Copy the diff from OpenSSL Github (ignore the 2 first lines) and put it in PROJECT_PATH/third_party/openssl/patches.
    The build script will then patch the sources.

How to build on Linux

Requirements

  • Boost >= 1.61.0
  • OpenSSL >= 1.0.2
  • Google Test = 1.7.0
  • CMake >= 2.8.11
  • Perl (OpenSSL build)
  • C++11 compiler (Clang, g++, etc.)

SSF_SECURITY

  • STANDARD: the project will be build with standard security features
  • FORCE_TCP_ONLY: the project will be built without security features to facilitate debugging

Process

  • Go in project directory
    cd PROJECT_PATH
  • Copy Boost archive in third_party/boost
    cp boost_1_XX_Y.tar.bz2 PROJECT_PATH/third_party/boost
  • Copy OpenSSL archive in third_party/openssl
    cp openssl-1.0.XY.tar.gz PROJECT_PATH/third_party/openssl
  • Copy GTest archive in third_party/gtest
    cp gtest-1.X.Y.zip PROJECT_PATH/third_party/gtest
  • Generate project
    git submodule update --init --recursive
    mkdir PROJECT_PATH/build
    cd PROJECT_PATH/build
    cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
  • Build project
    cd PROJECT_PATH/build
    cmake --build .

Known issues

  • GTest archive content has changed since its repository is on Github. Follow instructions in third_party/gtest/README.md to fix the build system

How to build on Mac OS X

Requirements

  • Boost >= 1.61.0
  • OpenSSL >= 1.0.2
  • Google Test = 1.7.0
  • CMake >= 2.8.11
  • Perl (OpenSSL build)
  • C++11 compiler (Clang, g++, etc.)

SSF_SECURITY

  • STANDARD: the project will be build with standard security features
  • FORCE_TCP_ONLY: the project will be built without security features to facilitate debugging

Process

  • Go in project directory
    cd PROJECT_PATH
  • Copy Boost archive in third_party/boost
    cp boost_1_XX_Y.tar.bz2 PROJECT_PATH/third_party/boost
  • Copy OpenSSL archive in third_party/openssl
    cp openssl-1.0.XY.tar.gz PROJECT_PATH/third_party/openssl
  • Copy GTest archive in third_party/gtest
    cp gtest-1.X.Y.zip PROJECT_PATH/third_party/gtest
  • Generate project
    git submodule update --init --recursive
    mkdir PROJECT_PATH/build
    cd PROJECT_PATH/build
    
    • Xcode project
      cmake .. -G "Xcode" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
    • Makefiles
      cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Release" -DSSF_SECURITY="STANDARD"
  • Build project
    cd PROJECT_PATH/build
    
    • Xcode project
      cmake --build . --config Release
    • Makefiles
      cmake --build .

Known issues

  • GTest archive content has changed since its repository is on Github. Follow instructions in third_party/gtest/README.md to fix the build system

Download SSF

Archive content

  • Executables: ssfs, ssfc, ssfcp
  • UPXed executables: upx-ssfs, upx-ssfc, upx-ssfcp
  • Test certificates ( testing purpose only)

Version history

Version history

2.2.0

  • Features:
    • Introducing microservices, base components for client features
    • Enable/disable microservices in configuration file
    • Gateway ports. Allow client to specify network listening interface on client features: -g command line option and gateway_ports microservice options (stream_listener and datagram_listener)
    • Server as relay only: -R command line option
  • Fixed bugs:
    • Delegate server hostname resolution to proxy
    • Fix server DOS on bogus connection
    • Fix a hang when the client stops during the connection stage
  • Configuration file:
    • http_proxy.credentials.reuse_ntlm and http_proxy.credentials.reuse_kerb: boolean instead of string

2.1.0

  • Features:
    • TLS layer over circuit layer
    • HTTP proxy support (CONNECT method), cf. configuration file
    • HTTP proxy authentication support (Basic, Digest, NTLM [windows only], Negotiate), cf. configuration file
    • Cross platform shell through socket (-X and -Y options)
      Default shell: cmd.exe on Windows, /bin/bash on Linux and OS X
    • Server network interface option
  • Fixed bugs:
    • Linux static link to libstdc++
    • Linux dependency to GLIBC2.14 (memcpy)
    • Stop behavior (signal instead of user input)
    • Port forwarding listening side on localhost only

2.0.0

  • BC break with version 1.*.*
  • Features:
    • New network layer based on SSF network framework

1.1.0

  • Features:
    • ssfcp: file copy between client and server
    • Rename executables:
      • SSF_Client ssfc
      • SSF_Server ssfs
  • Fixed bugs:
    • Crash issue due to exception when resolving endpoint
    • Exception safety
    • Windows compilation warnings (64bits)

1.0.0

  • Features:
    • Local and remote TCP port forwarding (-L and -R options)
    • Local and remote UDP port forwarding (-U and -V options)
    • Local and remote SOCKS server (-D and -F options)
    • Native relay protocol (-b option)
    • Multi platform (Windows, Linux and OSX)
    • TLS connection with the strongest cipher-suites
    • Standalone executables

FAQ

Contact
You can post requests, feedback or issues in the Github repository.
You can also contact us more directly: ssf.developer [at] gmail [dot] com
Build issues
Send us your compilation logs and your build machine information (OS, Boost, OpenSSL and GTest version).
The project compilation is tested against Visual Studio 2013-2015 (32/64 bits), gcc >= 4.8.4 (32/64 bits) and OS X 10.10 with Xcode 6.4 (64bits). It requires C++ compiler which supports C++11 features.
Execution issues
Send us your use case and your application logs. We will try to reproduce it and provide a fix or a workaround.

Security features

TLS usage

SSF is based on Boost.Asio for all its networking and it uses Asio wrapper for OpenSSL. TLS connections support only certificate authentication and enforce mutual authentication.

TLS options

The following TLS options are hardcoded (see OpenSSL documentation for more information):

  • Connection fails in case of absence of certificate from a peer
  • No SSLv1, v2 or v3 and no TLSv1.0 or v1.1 therefore forcing TLSv1.2
  • Reuse of Diffie-Hellman is forbidden
  • No ticket extension allowed

TLS cipher suggestions

The default cipher suite used in SSF is DHE-RSA-AES256-GCM-SHA384

However, the configuration file allows for any SSL cipher suite usage (see the Configuration section to know how). Here are the guidelines which led to the choice of this cipher:

  • Use ephemeral Diffie-Hellman to ensure perfect forward secrecy. Indeed, in that case, public and private keys will only be used for authentication and a new key will be negotiated independently for each connection. Therefore, even if a user private key of a user gets compromised at some point, the previous communications remain secure.
  • Avoid elliptic curves to avoid fishy NIST curves. Therefore, RSA is used for authentication.
  • Use a strong symmetric algorithm in it strongest version. Most computers now have more than enough computing power to support AES256 (especially with AES ASM instructions) so why not use it?
  • Use a block cipher mode which both guaranty confidentiality and integrity: GCM mode.
  • Use a strong hashing function: SHA384.

Generate your own cryptographic elements

Cryptographic suggestions

It might be wise to protect private keys with passphrases, especially on client sides. On the server side, the passphrase will have to be specified in the configuration file (see the Configuration section to know how). However, with a client, if the passphrase is needed and not specified in a configuration file, the user will be prompted to enter the passphrase manually.

Here is the command to encrypt an unencrypted RSA private key with the passphrase "passphrase":

openssl rsa -in private.key -out private.key -aes256 -passout pass:passphrase

Here is the command to change the passphrase of an encrypted RSA private key from "passphrase" to "new_passphrase":

openssl rsa -in private.key -out private.key -aes256 -passin pass:passphrase -passout pass:new_passphrase

Here is the command to remove the passphrase of an encrypted RSA private key with passphrase equal to "passphrase":

openssl rsa -in private.key -out private.key -passin pass:passphrase

Generate elements for TLS connections

In order to use SSF, it will be necessary to generate private keys, certificates and Diffie-Hellman parameters:

Generating Diffie-Hellman parameters

openssl dhparam 4096 -outform PEM -out dh4096.pem

Generating a self-signed Certification Authority (CA) ca.crt and its private key ca.key

openssl req -x509 -nodes -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3650

Then, create a file named extfile.txt containing the following lines:

[ v3_req_p ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca_p ]
basicConstraints = CA:TRUE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, keyCertSign

It will permit to create intermediary CA if needed.

Generating an intermediary CA (ca_int.crt, ca_int.key) signed with a CA (ca.crt, ca.key)

First, generate a private key ca_int.key and a signing request ca_int.csr:

openssl req -newkey rsa:4096 -nodes -keyout ca_int.key -out ca_int.csr

Then, sign with the CA (ca.crt, ca.key) the signing request to get the intermediary CA certificate ca_int.crt:

openssl x509 -extfile extfile.txt -extensions v3_ca_p -req -sha1 -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in ca_int.csr -out ca_int.crt
cat ca.crt >> ca_int.crt

Generating a private key private.key and its certificate certificate.cst signed with a CA ca.crt

First, generate a private key private.key and a signing request certificate.csr:

openssl req -newkey rsa:4096 -nodes -keyout private.key -out certificate.csr

Then, sign with the CA (ca.crt, ca.key) the signing request to get the certificate certificate.crt:

openssl x509 -extfile extfile.txt -extensions v3_req_p -req -sha1 -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in certificate.csr -out certificate.crt
cat ca.crt >> certificate.crt

Perfomances

The goal with SSF was to provide a high performance network tool so it could be used on high bandwidth links.

When testing OpenSSH to establish a secure link between two servers over a low latency gigabit Ethernet connection, the bandwidth of a TCP tunnel was limited to about 125 Mbits/s.

SSF, with all its default configurations (including a higher security cipher suite than OpenSSH), reached 600 Mbits/s. It seems that the limitation comes from the underlying cryptographic library (OpenSSL). Indeed, when compiled with the special flag FORCE_TCP_ONLY, the gigabit Ethernet link was saturated.

Test typology

  • Low latency gigabit Ethernet connection
  • Two servers and one client running on different computers (>Intel Core i7-3770T, >16GB DDR3)
  • Client establishes a TCP port forwarding to the second server passing through the first server
  • Receive and send random data through the forwarding link during 5 minutes

Developer corner

C++

SSF is implemented using C++11 to support a wider range of standard compilers (e.g. Visual Studio 2013, g++-4.8 for Ubuntu 14.04). As soon as C++14, and later C++17 are easily accessible (native/default) on every build platforms, the code will be updated to evolve with these standards.

SSF relies on the Boost libraries, especially Asio, and was designed to be extended. A special effort was made to ease the build process: CMake is used to generate any dev environment (ex: Visual Studio, XCode, Make...). The building process for third party libraries (Boost, OpenSSL, GoogleTest) is made easy with custom CMake scripts which automatically extract and build all the needed dependencies from sources. Just download and drop the latest third party source tarball in the project's third_party subdirectory, and you're ready to build. SSF also comes with a set of unit tests so that you can fork and tweak the code, and test your changes easily.

Extensible microservice framework and toolkit

The features of SSF framework are designed as microservices, allowing an easy integration of new functionalities. Checkout the documentation to know how to add your own custom features. SSF networking is based on Boost.Asio and provide objects with an Asio compliant interface. This aspect will be extended in a near future to provide a wide network toolkit (still based on Asio) permitting to quickly and easily design complex network protocols and communications.

Contribute

Do not hesitate to fork, emit requests or fill issues using GitHub.

About the project

SSF is developed and maintained by two Belgians C++ enthusiasts which care about security and performances.

We think that OpenSource is the right way to make the project evolve in its next generation.

Do not hesitate to post any requests, feedback or issues in the Github repository. We will be glad to answer and make this project better.

To contact us more directly: ssf.developer [at] gmail [dot] com