commit 5a255e406a578622f074259ece66e9d047d8ac98
parent 4dc8422e6e18ef09e771aed53b7a334c9d376d2e
Author: chris-belcher <chris-belcher@users.noreply.github.com>
Date: Wed, 23 May 2018 16:52:34 +0100
Add IP address whitelisting feature
Diffstat:
3 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
@@ -78,18 +78,20 @@ headers; and locks Electrum to connect only to your server, disabling the GUI
button to stop accidental connections. This helps avoid a user accidentally
ruining their privacy by connecting to public Electrum servers.
-Electrum Personal Server also works on [testnet bitcoin](https://en.bitcoin.it/wiki/Testnet). The Electrum wallet can be started in testnet mode with the command line flag `--testnet`.
+Electrum Personal Server also works on [testnet](https://en.bitcoin.it/wiki/Testnet) and [regtest](https://bitcoin.org/en/glossary/regression-test-mode). The Electrum wallet can be started in testnet mode with the command line flag `--testnet` or `--regtest`.
#### Exposure to the Internet
Other people should not be connecting to your server. They won't be
able to synchronize their wallet, and they could potentially learn all your
-wallet addresses.
+wallet addresses. They should also not be packet sniffing the connection
+because it is not encrypted securely.
By default the server will accept connections only from `localhost` so you
-should either run Electrum wallet from the same computer or use a SSH tunnel
-from another computer.
+should either run Electrum wallet from the same computer, or use an encrypted
+SSH tunnel from another computer, or use the IP address whitelisting feature to
+connect over your own LAN.
#### How is this different from other Electrum servers ?
diff --git a/config.cfg_sample b/config.cfg_sample
@@ -48,10 +48,15 @@ gap_limit = 25
[electrum-server]
# 0.0.0.0 to accept connections from any IP
#127.0.0.1 to accept from only localhost
-# recommend you accept localhost only, for connecting remotely use a ssh tunnel
host = 127.0.0.1
port = 50002
+# space-separated whitelist of IP addresses
+# accepts CIDR notation eg 192.168.0.0/16 or 2a01:4f8:1f1::/120
+# star (*) means all are accepted
+# generally requires host binding (above) to be 0.0.0.0
+ip_whitelist = *
+
#uses the default one, which is fine because by default nobody should be
# allowed to connect to your server or scan your packets
#to generate another certificate see https://github.com/spesmilo/electrum-server/blob/ce1b11d7f5f7a70a3b6cc7ec1d3e552436e54ffe/HOWTO.md#step-8-create-a-self-signed-ssl-cert
diff --git a/server.py b/server.py
@@ -4,6 +4,7 @@ import socket, time, json, datetime, struct, binascii, ssl, os, os.path
from configparser import ConfigParser, NoSectionError, NoOptionError
from collections import defaultdict
import traceback, sys, platform
+from ipaddress import ip_network, ip_address
from electrumpersonalserver.jsonrpc import JsonRpc, JsonRpcError
import electrumpersonalserver.hashes as hashes
@@ -295,8 +296,8 @@ def create_server_socket(hostport):
log("Listening for Electrum Wallet on " + str(hostport))
return server_sock
-def run_electrum_server(hostport, rpc, txmonitor, poll_interval_listening,
- poll_interval_connected, certfile, keyfile):
+def run_electrum_server(rpc, txmonitor, hostport, ip_whitelist,
+ poll_interval_listening, poll_interval_connected, certfile, keyfile):
log("Starting electrum server")
server_sock = create_server_socket(hostport)
server_sock.settimeout(poll_interval_listening)
@@ -306,12 +307,16 @@ def run_electrum_server(hostport, rpc, txmonitor, poll_interval_listening,
while sock == None:
try:
sock, addr = server_sock.accept()
+ if not any([ip_address(addr[0]) in ipnet
+ for ipnet in ip_whitelist]):
+ debug(addr[0] + " not in whitelist, closing")
+ raise ConnectionRefusedError()
sock = ssl.wrap_socket(sock, server_side=True,
certfile=certfile, keyfile=keyfile,
ssl_version=ssl.PROTOCOL_SSLv23)
except socket.timeout:
on_heartbeat_listening(txmonitor)
- except ssl.SSLError:
+ except (ConnectionRefusedError, ssl.SSLError):
sock.close()
sock = None
@@ -504,14 +509,22 @@ def main():
return
hostport = (config.get("electrum-server", "host"),
int(config.get("electrum-server", "port")))
+ ip_whitelist = []
+ for ip in config.get("electrum-server", "ip_whitelist").split(" "):
+ if ip == "*":
+ #matches everything
+ ip_whitelist.append(ip_network("0.0.0.0/0"))
+ ip_whitelist.append(ip_network("::0/0"))
+ else:
+ ip_whitelist.append(ip_network(ip, strict=False))
poll_interval_listening = int(config.get("bitcoin-rpc",
"poll_interval_listening"))
poll_interval_connected = int(config.get("bitcoin-rpc",
"poll_interval_connected"))
certfile = config.get("electrum-server", "certfile")
keyfile = config.get("electrum-server", "keyfile")
- run_electrum_server(hostport, rpc, txmonitor, poll_interval_listening,
- poll_interval_connected, certfile, keyfile)
+ run_electrum_server(rpc, txmonitor, hostport, ip_whitelist,
+ poll_interval_listening, poll_interval_connected, certfile, keyfile)
if __name__ == "__main__":
main()