Сделать удаленное подключение RPC к серверу биткойн безопасным

Я настроил биткойн-сервер на сервере Ubuntu и могу удаленно выполнять команды на сервере. Я делаю это с помощью Java/RPC. Чтобы выполнить команду, мне нужно указать имя пользователя и пароль. Но я думаю, что это было бы недостаточно безопасности. Вот почему я спрашиваю здесь. Как я могу сделать это соединение действительно безопасным? Сначала я думал, что могу разрешать запросы только с определенного IP-адреса, но это не сработает, потому что мое приложение работает на Google App Engine и, следовательно, не имеет статического IP-адреса.

Любые идеи, как сделать это безопасным? Вот мой код, если интересно:

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());      
    }
}
Сначала вы сказали, что у вас есть сервер Ubuntu с работающим биткойном, а затем AppEngine. Который из них?

Ответы (2)

РЕДАКТИРОВАТЬ : я только что заметил, что ваш вопрос требует конкретного решения для App Engine. Это решение применимо только в том случае, если у вас есть 100% контроль над сервером Linux, на котором выполняется ваш код, поэтому это не работает в App Engine (или я понятия не имею, есть ли в настоящее время возможность построения туннеля). В любом случае я рекомендую вам переместить ваш код на виртуальный сервер из ядра приложения, чтобы лучше контролировать свой стек, так как вы можете довольно быстро столкнуться с ограничениями App Engine, опрашивая биткойн для транзакций.

Создайте туннель TCP/IP через SSH от компьютера, на котором выполняется ваш код, к серверу, на котором работает bitcoind.

Одним из простых способов создания такого туннеля, который перезапускается при отключении, является AutoSSH .

Вот один пример скрипта AutoSSH:

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

Рекомендации:

  1. Создайте API-REST, WS или любой аналог для связи между узлом и внешним миром.

  2. Максимально ограничьте доступ к узлу RPC (Доступ к узлу только локально), вы должны рассматривать узел биткойн как базу данных. используйте свой сервер ubuntu только для запуска RPC и внешней службы.

  3. Никогда не выставляйте подключение к узлу наружу. проверьте документацию по биткойн RPC для получения дополнительной информации.

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

Извините, мой автоматический корректор заставил меня поверить, что это форум на испанском языке.