Skip to content

Commit 6adb8d1

Browse files
committed
Add manual RPC connection with security warnings
- Implement test_and_connect_manual backend command - Add remote connection security warning modal - Add "Forget Saved Credentials" functionality - Create comprehensive manual connection guide for all platforms - Change button text to "Connect Remotely"
1 parent c0e8c87 commit 6adb8d1

4 files changed

Lines changed: 459 additions & 12 deletions

File tree

MANUAL_CONNECTION_GUIDE.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# Manual RPC Connection Guide
2+
3+
Connect VerusIDX to a Verus daemon running on another computer.
4+
5+
---
6+
7+
## Quick Start
8+
9+
### 1. Find Your Daemon's Information
10+
11+
**On the computer running Verus daemon:**
12+
13+
#### macOS
14+
```bash
15+
# Get IP address
16+
ifconfig | grep "inet " | grep -v 127.0.0.1
17+
```
18+
Look for IP starting with `192.168.` or `10.0.`
19+
20+
**Config location:** `~/Library/Application Support/Komodo/vrsctest/vrsctest.conf`
21+
22+
#### Windows
23+
1. Settings → Network & Internet → Properties
24+
2. Find **IPv4 Address** (e.g., `192.168.1.105`)
25+
26+
**Config location:** `C:\Users\YourUsername\AppData\Roaming\Komodo\vrsctest\vrsctest.conf`
27+
28+
#### Linux
29+
```bash
30+
# Get IP address
31+
ip addr show | grep "inet "
32+
```
33+
Look for IP starting with `192.168.` or `10.0.`
34+
35+
**Config location:** `~/.komodo/vrsctest/vrsctest.conf`
36+
37+
---
38+
39+
### 2. Configure Daemon for Remote Access
40+
41+
**Edit the config file** (vrsctest.conf or VRSC.conf):
42+
43+
```
44+
rpchost=0.0.0.0
45+
rpcallowip=0.0.0.0/0
46+
rpcuser=your_username
47+
rpcpassword=your_password
48+
rpcport=18843
49+
```
50+
51+
**Restart the daemon** after saving changes.
52+
53+
---
54+
55+
### 3. Open Firewall Port
56+
57+
#### macOS
58+
System Settings → Network → Firewall → Options → Add port 18843
59+
60+
#### Windows
61+
1. Start → "Windows Defender Firewall" → Advanced Settings
62+
2. Inbound Rules → New Rule → Port
63+
3. TCP, port `18843` → Allow the connection
64+
4. Check: Domain, Private, Public → Name: "Verus RPC"
65+
66+
**Network profile:** Settings → Network → Set to **Private** (not Public)
67+
68+
#### Linux (Ubuntu/Debian)
69+
```bash
70+
sudo ufw allow 18843/tcp
71+
```
72+
73+
---
74+
75+
### 4. Connect in VerusIDX
76+
77+
On the computer running VerusIDX:
78+
79+
1. Launch app → Show manual connection
80+
2. Enter:
81+
- **Host:** Daemon computer's IP (e.g., `192.168.1.105`)
82+
- **Port:** `18843` (testnet) or `27486` (mainnet)
83+
- **Username:** Value after `rpcuser=` in config
84+
- **Password:** Value after `rpcpassword=` in config
85+
3. Click "Connect Remotely"
86+
87+
---
88+
89+
## Security Considerations
90+
91+
### ⚠️ Important Security Notes
92+
93+
**Unencrypted Connection:**
94+
- Manual RPC uses HTTP (not HTTPS)
95+
- Credentials and data sent in **plain text**
96+
- Anyone on the same network can intercept traffic
97+
98+
**Safe Use Cases:**
99+
- ✅ Same trusted home network
100+
- ✅ Through SSH tunnel (see below)
101+
- ✅ Through VPN
102+
- ❌ Public Wi-Fi / untrusted networks
103+
104+
### Remote Warning
105+
106+
When connecting to a non-localhost daemon, the app will show a security warning. Only proceed if:
107+
- You own both computers
108+
- You're on a trusted private network
109+
- You're using an SSH tunnel or VPN
110+
111+
---
112+
113+
## Advanced: SSH Tunnel (Encrypted)
114+
115+
For maximum security, use an SSH tunnel to encrypt all RPC traffic.
116+
117+
### Setup
118+
119+
#### 1. Enable SSH Server (Daemon Computer)
120+
121+
**macOS:**
122+
System Settings → Sharing → Enable "Remote Login"
123+
124+
**Windows:**
125+
Settings → Apps → Optional Features → Add "OpenSSH Server"
126+
Services → Start "OpenSSH SSH Server"
127+
128+
**Linux:**
129+
```bash
130+
sudo apt install openssh-server
131+
sudo systemctl start ssh
132+
```
133+
134+
#### 2. Create Tunnel (VerusIDX Computer)
135+
136+
**macOS/Linux:**
137+
```bash
138+
ssh -L 18843:localhost:18843 username@daemon-ip-address
139+
```
140+
141+
**Windows PowerShell:**
142+
```powershell
143+
ssh -L 18843:localhost:18843 username@daemon-ip-address
144+
```
145+
146+
Replace:
147+
- `username` = Your account name on daemon computer
148+
- `daemon-ip-address` = Daemon's IP (e.g., `192.168.1.105`)
149+
150+
**Keep terminal window open while using VerusIDX**
151+
152+
#### 3. Connect in App
153+
154+
- **Host:** `127.0.0.1` (localhost - traffic goes through encrypted tunnel)
155+
- **Port:** `18843`
156+
- **Username/Password:** From Verus config
157+
158+
---
159+
160+
## Troubleshooting
161+
162+
### "Connection test failed"
163+
164+
**Check daemon is running:**
165+
```bash
166+
# macOS/Linux
167+
ps aux | grep verus
168+
169+
# Windows PowerShell
170+
Get-Process | Select-String verus
171+
```
172+
173+
**Test RPC manually:**
174+
```bash
175+
curl -u username:password --data-binary '{"jsonrpc":"1.0","method":"getinfo","params":[]}' http://daemon-ip:18843
176+
```
177+
178+
**Common issues:**
179+
- Firewall blocking port 18843
180+
- `rpchost` still set to `127.0.0.1` (change to `0.0.0.0`)
181+
- Wrong IP address (use `ipconfig`/`ifconfig` to verify)
182+
- Daemon not restarted after config changes
183+
184+
### "Daemon offline or unreachable"
185+
186+
**Verify port is open:**
187+
```bash
188+
# macOS/Linux
189+
nc -zv daemon-ip 18843
190+
191+
# Windows PowerShell
192+
Test-NetConnection -ComputerName daemon-ip -Port 18843
193+
```
194+
195+
If this fails, firewall is blocking the connection.
196+
197+
---
198+
199+
## Best Practices
200+
201+
1. **Use strong passwords** in RPC config
202+
2. **Don't remember credentials** for remote connections unless it's your own server
203+
3. **Use SSH tunnel** when connecting over internet or untrusted networks
204+
4. **Set network to Private** on Windows (not Public)
205+
5. **Restart daemon** after any config changes
206+
6. **Close port 18843** in firewall when not in use for added security
207+
208+
---
209+
210+
## FAQ
211+
212+
**Q: Can I connect over the internet?**
213+
A: Yes, but you **must** use an SSH tunnel or VPN. Never expose RPC directly to the internet.
214+
215+
**Q: What's the difference between localhost and remote?**
216+
A: Localhost (`127.0.0.1`) connects to daemon on same computer. Remote connects to different computer using its IP address.
217+
218+
**Q: Do I need to open ports for localhost connections?**
219+
A: No, firewall rules only apply to remote connections.
220+
221+
**Q: Can multiple VerusIDX instances connect to one daemon?**
222+
A: Yes, one daemon can handle multiple RPC connections simultaneously.
223+
224+
**Q: Why does the app say "Connect Remotely" even for localhost?**
225+
A: The manual connection form handles both local and remote connections. Button text is simplified for clarity.
226+
227+
---
228+
229+
## Support
230+
231+
For issues or questions:
232+
- GitHub: https://github.com/VerusCoin/verusidx/issues
233+
- Discord: Verus Community
234+
235+
**Remember:** Manual connection with proper security (SSH tunnel or trusted private network) enables powerful remote access to your Verus daemon!

src-tauri/src/commands/mod.rs

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -416,25 +416,25 @@ pub async fn connect_to_chain(
416416
state: State<'_, AppState>
417417
) -> Result<bool, String> {
418418
let discovered_chains = state.discovered_chains.read().await;
419-
419+
420420
// Log chain connection attempts
421421
eprintln!("Connecting to chain: {}", chain_name);
422-
422+
423423
// Find the requested chain (case-insensitive comparison)
424424
let chain = discovered_chains
425425
.iter()
426426
.find(|c| c.name.to_string() == chain_name.to_lowercase())
427-
.ok_or(format!("Chain '{}' not found in discovered chains. Available: {:?}",
428-
chain_name,
427+
.ok_or(format!("Chain '{}' not found in discovered chains. Available: {:?}",
428+
chain_name,
429429
discovered_chains.iter().map(|c| c.name.to_string()).collect::<Vec<_>>()))?;
430-
430+
431431
if !chain.is_active {
432432
return Err("Chain is not active/reachable".to_string());
433433
}
434-
434+
435435
// Create new client for this chain
436436
let client = VerusRpcClient::new(chain.credentials.clone()).map_err(|e| e.to_string())?;
437-
437+
438438
// Test the connection
439439
match client.test_connection().await {
440440
Ok(_) => {
@@ -447,6 +447,67 @@ pub async fn connect_to_chain(
447447
}
448448
}
449449

450+
#[tauri::command]
451+
pub async fn test_and_connect_manual(
452+
host: String,
453+
port: u16,
454+
username: String,
455+
password: String,
456+
state: State<'_, AppState>
457+
) -> Result<Value, String> {
458+
eprintln!("Testing manual RPC connection to {}:{}", host, port);
459+
460+
// Create credentials
461+
let credentials = RpcCredentials {
462+
username,
463+
password,
464+
host,
465+
port,
466+
};
467+
468+
// Validate credentials format
469+
CredentialManager::validate_credentials(&credentials)
470+
.map_err(|e| e.to_string())?;
471+
472+
// Create RPC client
473+
let client = VerusRpcClient::new(credentials.clone())
474+
.map_err(|e| format!("Failed to create RPC client: {}", e))?;
475+
476+
// Test the connection
477+
client.test_connection().await
478+
.map_err(|e| format!("Connection test failed: {}", e))?;
479+
480+
// Get chain info to determine which chain we're connected to
481+
let info: Value = client.call("getinfo", json!([])).await
482+
.map_err(|e| format!("Failed to get chain info: {}", e))?;
483+
484+
// Determine chain name from the response
485+
let chain_name = if let Some(name) = info.get("name").and_then(|v| v.as_str()) {
486+
name.to_string()
487+
} else {
488+
// Fallback: determine from port
489+
match port {
490+
18843 => "vrsctest".to_string(),
491+
27486 => "vrsc".to_string(),
492+
_ => "unknown".to_string(),
493+
}
494+
};
495+
496+
eprintln!("Successfully connected to chain: {}", chain_name);
497+
498+
// Store the working client in app state
499+
let mut active_client = state.active_client.write().await;
500+
*active_client = Some(client);
501+
502+
// Return connection info
503+
Ok(json!({
504+
"success": true,
505+
"chainName": chain_name,
506+
"host": credentials.host,
507+
"port": credentials.port
508+
}))
509+
}
510+
450511
// Credential Management Commands
451512
#[tauri::command]
452513
pub async fn store_credentials(

src-tauri/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use commands::{
55
AppState, greet,
66
get_info, get_wallet_info, get_mining_info, z_get_total_balance, get_blockchain_info,
77
list_identities, get_identity, get_identity_content, verify_message, verify_hash, list_currencies, get_currency, get_currency_converters, get_currency_state, get_offers, list_open_offers, close_offers, make_offer, take_offer,
8-
discover_chains, get_discovered_chains, connect_to_chain, store_credentials,
8+
discover_chains, get_discovered_chains, connect_to_chain, test_and_connect_manual, store_credentials,
99
load_credentials, clear_credentials, list_stored_chains, get_expected_config_paths,
1010
get_block_count, list_address_groupings, estimate_conversion, convert_currency, send_currency,
1111
convert_to_verusidx, register_name_commitment, register_identity, revoke_identity, recover_identity, update_identity, set_identity_timelock,
@@ -45,6 +45,7 @@ pub fn run() {
4545
discover_chains,
4646
get_discovered_chains,
4747
connect_to_chain,
48+
test_and_connect_manual,
4849
store_credentials,
4950
load_credentials,
5051
clear_credentials,

0 commit comments

Comments
 (0)