Machen Sie die Remote-RPC-Verbindung zum Bitcoin-Server sicher

Ich richte einen Bitcoin-Server auf einem Ubuntu-Server ein und kann Befehle auf dem Server remote ausführen. Ich mache das mit Java/RPC. Um einen Befehl auszuführen, muss ich einen Benutzernamen und ein Passwort angeben. Aber ich denke, das wäre nicht genug Sicherheit. Deshalb frage ich hier. Wie kann ich diese Verbindung wirklich sicher machen? Zuerst dachte ich, ich könnte nur Anfragen von einer bestimmten IP zulassen, aber das wird nicht funktionieren, da meine App auf Googles App Engine läuft und daher keine statische IP hat.

Irgendwelche Ideen, wie man das sicher macht? Hier ist mein Code, falls es von Interesse ist:

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());      
    }
}
Sie sagten zuerst, Sie hätten einen Ubuntu-Server, auf dem Bitcoin läuft, und dann AppEngine. Welches ist es?

Antworten (2)

BEARBEITEN : Ich habe gerade bemerkt, dass Ihre Frage nach einer App Engine-spezifischen Lösung fragt. Diese Lösung gilt nur, wenn Sie 100 % Kontrolle über den Linux-Server haben, auf dem Ihr Code ausgeführt wird. Dies funktioniert also nicht mit App Engine (oder ich habe keine Ahnung, ob es heutzutage die Fähigkeit zum Tunnelaufbau hat). In jedem Fall empfehle ich Ihnen, Ihren Code von der App Engine auf einen virtuellen Server zu verschieben, um mehr Kontrolle über Ihren Stack zu haben, da Sie beim Abfragen von Bitcoin nach Transaktionen ziemlich schnell auf App Engine-Einschränkungen stoßen könnten.

Erstellen Sie über SSH einen TCP/IP-Tunnel von dem Computer, auf dem Ihr Code ausgeführt wird, zu dem Server, auf dem bitcoind.

Eine einfache Möglichkeit, einen solchen Tunnel aufzubauen, der sich beim Trennen neu startet, ist AutoSSH .

Hier ist ein AutoSSH-Beispielskript:

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

Empfehlungen:

  1. Erstellen Sie ein API-REST, WS oder ein Äquivalent für die Kommunikation zwischen dem Knoten und der Umgebung.

  2. Beschränken Sie den Zugriff auf den RPC-Knoten so weit wie möglich (Zugriff auf den Knoten nur lokal), Sie sollten den Bitcoin-Knoten als Datenbank betrachten. Verwenden Sie Ihren Ubuntu-Server nur, um RPC und den externen Dienst auszuführen.

  3. Geben Sie niemals eine Verbindung zum Knoten nach außen frei. Weitere Informationen finden Sie in der Bitcoin RPC-Dokumentation.

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

Entschuldigung, mein automatischer Korrekturleser hat mich glauben gemacht, dass dies das Forum auf Spanisch ist.