以太坊节点geth的rpc采用加密访问方式

1 、为什么RPC要加密访问

geth给用户暴露了很多Json-RPC接口API,可以让web3.js或web3j库来通过这些接口来访问geth节点,可以实现远程查询转账等功能。但是geth暴露的这些接口是未经过任何加密处理的不安全接口。如果geth使用这种方式启动RPC:

1
geth --datadir "/www/ethereum/eth/test" --rpc --rpcapi "eth,web3,miner,admin,personal,net" --rpcaddr "0.0.0.0" --rpccorsdomain "*" --nodiscover --networkid 15

--rpcaddr 0.0.0.0 这个允许所有用户都访问rpc端口。这样外部用户都可以访问这个geth节点,geth暴露在公网上面,可能会遭受黑客各种攻击。比如DDoS攻击。

慢雾团队披露的黑客从用户存在geth节点上的钱包偷币的事件,就是黑客通过暴露在外网的RPC接口作案的例子。按照最新的研究报告,凡是在暴露在公网的geth节点上解锁过的钱包,都可能存在安全风险,即使已经关闭RPC端口,黑客仍然可以通过已经用钱包签名过的数据随时从用户钱包中把数字货币偷走。

如果geth节点不得不暴露在公网上面,则会面临很多安全风险。一个可能的补救措施是对RPC访问进行加密。通过nginx的HTTP basic Auth(Http基本认证)技术,可以实现更高的安全。

2、Nginx Basic HTTP Authentication原理

通过配置nginx的反向代理和加密技术,可以给运行在linux上的应用程序分配一个新的url,访问应用程序就相当于访问这个url。外部用户想访问这个url,必须输入用户名和密码,否则访问会被拒绝。对于geth节点,以前必须对所有用户暴露rpc端口,采用NBHA技术,则给geth分配一个对于的url,需要用户名和密码才能访问geth节点。这个时候,geth节点不必对外开放RPC端口。

3、Nginx Basic HTTP Authentication实现

下面以centos 7.6操作系统为例,讲解在利用nginx实现Http基本认证的步骤。

步骤1 安装软件

1
2
yum install nginx
yum install httpd

步骤2 创建认证用户名和密码

1
 sudo htpasswd -c /usr/local/nginx/conf/ssl/geth.htpasswd rpcuser

将在/usr/local/nginx/conf/ssl/下创建名为geth.htpasswd的密码文件,用户名设置为rpcuser。输入上面命令,会提示用户输入俩次密码。

步骤3 修改nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server
    {
        listen 8080;
        root  /www/eth;

        location /
        {
            try_files $uri $uri/ =404;
        }
        location /eth{
            auth_basic "Restricted Area";
            auth_basic_user_file /usr/local/nginx/conf/ssl/geth.htpasswd;
            proxy_pass http://localhost:8545;

            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
                #
                # Tell client that this pre-flight info is valid for 20 days
                #
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
        }

        access_log  /www/wwwlogs/eth.log;
        error_log  /www/wwwlogs/eth-error.log;
    }

步骤4 更新nginx服务

1
sudo /etc/init.d/nginx reload

步骤5 启动节点

1
geth --datadir "/www/ethereum/eth/test" --rpc --rpcapi "eth,web3,miner,admin,personal,net" --rpcaddr "127.0.0.1" --rpccorsdomain "*" --nodiscover --networkid 15