<p><strong>EDIT</strong>: I just noticed your question asks for App Engine specific solution. This solution only applies if you have 100% control over the Linux server running your code, so this does not work on App Engine (or I have no idea does it nowadays have capability of tunnel building). In any case I recommend you to move your code to a virtual server from the app engine to have more control over your stack, as you might hit App Engine limitations quite fast if polling bitcoind for transactions.</p>

<p>Build a TCP/IP tunnel through SSH from the computer running your code to the server running <code>bitcoind</code>.                            </p>

<p>One easy way to build such a tunnel which restarts itself on disconnect is <a href="http://www.harding.motd.ca/autossh/" rel="nofollow noreferrer">AutoSSH</a>.</p>

<p>Here is one AutoSSH example script:</p>

<p><a href="http://www.ubuntugeek.com/automatically-restart-ssh-sessions-and-tunnels-using-autossh.html" rel="nofollow noreferrer">http://www.ubuntugeek.com/automatically-restart-ssh-sessions-and-tunnels-using-autossh.html</a> </p>

CC BY-SA 4.0
2014-02-03T13:32:51.830Z
2019-04-11T01:38:21.653Z
2019-04-11T01:38:21.653Z
Mikko Ohtamaa
<p><strong><em>Recommendations:</em></strong></p>

<ol>
<li><p>Build an API-REST, WS, or any equivalent for communication between the node and the outside.</p></li>
<li><p>Limit access to the RPC node as much as possible (Access the node only locally), you should consider the bitcoin node as a data base. use your ubuntu server only to run RPC and the external service.</p></li>
<li><p>Never expose a connection to the node to the outside. check the Bitcoin RPC documentation for more information.</p></li>
</ol>

<p><a href="https://bitcoincore.org/en/doc/" rel="nofollow noreferrer">https://bitcoincore.org/en/doc/</a></p>

<p>Sorry, my automatic proofreader made me believe that this is the forum in Spanish.</p>

CC BY-SA 4.0
2018-11-21T01:34:50.107Z
2018-11-21T01:34:50.107Z
La Thortilla
<p>I set up a bitcoind server on an Ubuntu server and I can remotely execute commands on the server. I am doing this with Java/RPC. To execute a command I need to provide a username and password. But I think that would not be enough security. That's why I am asking here. How can I make this connection really secure? First, I thought I could only allow requests from a specific IP, but that will not work because my app runs on Google's App Engine and therefore does not have a static IP.</p>

<p>Any ideas how to make this secure? Here is my code, if it is of interest:</p>

<pre><code>import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class RPCClient {

    private static final String COMMAND_GET_BALANCE = "getbalance";
    private static final String COMMAND_GET_INFO = "getinfo";
    private static final String COMMAND_GET_NEW_ADDRESS = "getnewaddress";

    private JSONObject invokeRPC(String id, String method, List&lt;String&gt; params) {

//      CloseableHttpClient httpclient = HttpClientBuilder.create().build();
//      
//      httpclient.getCredentialsProvider();
        DefaultHttpClient httpclient = new DefaultHttpClient();

        JSONObject json = new JSONObject();
        json.put("id", id);
        json.put("method", method);
        if (null != params) {
            JSONArray array = new JSONArray();
            array.addAll(params);
            json.put("params", params);
        }
        JSONObject responseJsonObj = null;
        try {
            httpclient.getCredentialsProvider().setCredentials(new AuthScope("55.233.188.139", 9332),
                    new UsernamePasswordCredentials("myUser", "mySuperSecurePW"));
            StringEntity myEntity = new StringEntity(json.toJSONString());
            System.out.println(json.toString());
            HttpPost httppost = new HttpPost("http://55.233.188.139:9332");
            httppost.setEntity(myEntity);

            System.out.println("executing request" + httppost.getRequestLine());
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
                // System.out.println(EntityUtils.toString(entity));
            }
            JSONParser parser = new JSONParser();
            responseJsonObj = (JSONObject) parser.parse(EntityUtils.toString(entity));
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (org.json.simple.parser.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
        }
        return responseJsonObj;
    }

    public Double getBalance(String account) {
        String[] params = { account };
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), COMMAND_GET_BALANCE, Arrays.asList(params));
        return (Double)json.get("result");
    }

    public String getNewAddress(String account) {
        String[] params = { account };
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), COMMAND_GET_NEW_ADDRESS, Arrays.asList(params));
        return (String)json.get("result");
    }

    public JSONObject getInfo() {
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), COMMAND_GET_INFO, null);
        return (JSONObject)json.get("result");
    }

    public JSONObject getInfo(String command) {
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), command, null);
        return (JSONObject)json.get("result");
    }

    public static void main(String[] args) {
        System.out.println(new RPCClient().getInfo());      
    }
}
</code></pre>

CC BY-SA 3.0
2014-02-03T12:11:16.797Z
You first said you had an Ubuntu server with bitcoind running, and then AppEngine. Which one is it?
Luca Matteis
<bitcoind><security><api><json-rpc>
Make remote RPC connection to bitcoind server secure
jan
# Make remote RPC connection to bitcoind server secure

(Asked by: username_0 on 2014-02-03)

I set up a bitcoind server on an Ubuntu server and I can remotely execute commands on the server. I am doing this with Java/RPC. To execute a command I need to provide a username and password. But I think that would not be enough security. That's why I am asking here. How can I make this connection really secure? First, I thought I could only allow requests from a specific IP, but that will not work because my app runs on Google's App Engine and therefore does not have a static IP.

Any ideas how to make this secure? Here is my code, if it is of interest:

```
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class RPCClient {

    private static final String COMMAND_GET_BALANCE = "getbalance";
    private static final String COMMAND_GET_INFO = "getinfo";
    private static final String COMMAND_GET_NEW_ADDRESS = "getnewaddress";

    private JSONObject invokeRPC(String id, String method, List<String> params) {

//      CloseableHttpClient httpclient = HttpClientBuilder.create().build();
//      
//      httpclient.getCredentialsProvider();
        DefaultHttpClient httpclient = new DefaultHttpClient();

        JSONObject json = new JSONObject();
        json.put("id", id);
        json.put("method", method);
        if (null != params) {
            JSONArray array = new JSONArray();
            array.addAll(params);
            json.put("params", params);
        }
        JSONObject responseJsonObj = null;
        try {
            httpclient.getCredentialsProvider().setCredentials(new AuthScope("55.233.188.139", 9332),
                    new UsernamePasswordCredentials("myUser", "mySuperSecurePW"));
            StringEntity myEntity = new StringEntity(json.toJSONString());
            System.out.println(json.toString());
            HttpPost httppost = new HttpPost("http://55.233.188.139:9332");
            httppost.setEntity(myEntity);

            System.out.println("executing request" + httppost.getRequestLine());
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
                // System.out.println(EntityUtils.toString(entity));
            }
            JSONParser parser = new JSONParser();
            responseJsonObj = (JSONObject) parser.parse(EntityUtils.toString(entity));
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (org.json.simple.parser.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
        }
        return responseJsonObj;
    }

    public Double getBalance(String account) {
        String[] params = { account };
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), COMMAND_GET_BALANCE, Arrays.asList(params));
        return (Double)json.get("result");
    }

    public String getNewAddress(String account) {
        String[] params = { account };
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), COMMAND_GET_NEW_ADDRESS, Arrays.asList(params));
        return (String)json.get("result");
    }

    public JSONObject getInfo() {
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), COMMAND_GET_INFO, null);
        return (JSONObject)json.get("result");
    }

    public JSONObject getInfo(String command) {
        JSONObject json = invokeRPC(UUID.randomUUID().toString(), command, null);
        return (JSONObject)json.get("result");
    }

    public static void main(String[] args) {
        System.out.println(new RPCClient().getInfo());      
    }
}

```

**Tags:** bitcoind, security, api, json-rpc

> **Comments:**
> **username_1**: You first said you had an Ubuntu server with bitcoind running, and then AppEngine. Which one is it?  

---

## 2 answers

### Answer by username_2 on 2014-02-03. Score: 2

**EDIT**: I just noticed your question asks for App Engine specific solution. This solution only applies if you have 100% control over the Linux server running your code, so this does not work on App Engine (or I have no idea does it nowadays have capability of tunnel building). In any case I recommend you to move your code to a virtual server from the app engine to have more control over your stack, as you might hit App Engine limitations quite fast if polling bitcoind for transactions.

Build a TCP/IP tunnel through SSH from the computer running your code to the server running `bitcoind`.

One easy way to build such a tunnel which restarts itself on disconnect is [AutoSSH](http://www.harding.motd.ca/autossh/).

Here is one AutoSSH example script:

<http://www.ubuntugeek.com/automatically-restart-ssh-sessions-and-tunnels-using-autossh.html>


---

### Answer by username_3 on 2018-11-21. Score: 1

***Recommendations:***

1. Build an API-REST, WS, or any equivalent for communication between the node and the outside.
2. Limit access to the RPC node as much as possible (Access the node only locally), you should consider the bitcoin node as a data base. use your ubuntu server only to run RPC and the external service.
3. Never expose a connection to the node to the outside. check the Bitcoin RPC documentation for more information.

<https://bitcoincore.org/en/doc/>

Sorry, my automatic proofreader made me believe that this is the forum in Spanish.


---

