lanet 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/index.html +256 -129
- data/lib/lanet/traceroute.rb +66 -92
- data/lib/lanet/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fa5904938004f84fe7b8d599da632140a532925cd0a0c48d5986d44443c0987
|
4
|
+
data.tar.gz: f039a015dcd75704b7fe80f2a84afbd758505048e78bc86001b9821c1be7a353
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac7892c9bd9179483ea9ebb796fb567a11f79aab6197b1c49a11d2797167e91c59be5da17e861a3e08069bc4ff745eae8534e8cdcda516739906a8011ab9ffc8
|
7
|
+
data.tar.gz: ef408dedc43f2461c69d0a00ae207f4bd139e06f171cb5cfd0fd6f40e58d2e0aa1bc59403428587f6982a378418ff241fecb1805254b37ea63d1a39ccc8116e3
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.5.1] - 2025-03-20
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
- Optimized traceroute implementation for better performance and code readability
|
12
|
+
- Simplified protocol selection logic with dedicated methods
|
13
|
+
- Improved error handling for socket operations
|
14
|
+
- Enhanced hostname extraction in traceroute results
|
15
|
+
- Reorganized code structure for better maintainability
|
16
|
+
- Added Windows-specific socket handling optimizations
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
- Fixed redundant code in socket handling for different operating systems
|
20
|
+
- Improved error messages for unprivileged traceroute attempts
|
21
|
+
- Fixed potential memory leaks in socket resource management
|
22
|
+
- Added proper handling for non-standard traceroute output formats
|
23
|
+
|
8
24
|
## [0.5.0] - 2025-03-12
|
9
25
|
|
10
26
|
### Added
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -20,7 +20,7 @@ A lightweight, powerful LAN communication tool that enables secure message excha
|
|
20
20
|
- **Digital Signatures**: Ensure message authenticity and integrity
|
21
21
|
- **File Transfers**: Securely send encrypted files over the LAN with progress tracking and integrity verification
|
22
22
|
- **Mesh Networking**: Create resilient mesh networks for decentralized communication, enabling messages to be routed through multiple hops without central infrastructure
|
23
|
-
- **Advanced Traceroute**: Analyze network paths using multiple protocols (ICMP, UDP, and TCP)
|
23
|
+
- **Advanced Traceroute**: Analyze network paths using multiple protocols (ICMP, UDP, and TCP) with intelligent fallback mechanisms
|
24
24
|
|
25
25
|
## Security Features
|
26
26
|
|
data/index.html
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html lang="en">
|
3
|
+
|
3
4
|
<head>
|
4
5
|
<meta charset="UTF-8">
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
@@ -7,188 +8,297 @@
|
|
7
8
|
<style>
|
8
9
|
body {
|
9
10
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
10
|
-
line-height: 1.7;
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
line-height: 1.7;
|
12
|
+
/* Increased line height for better readability */
|
13
|
+
color: #34495e;
|
14
|
+
/* Darker, more professional text color */
|
15
|
+
max-width: 980px;
|
16
|
+
/* Slightly wider max width for content */
|
17
|
+
margin: 20px auto;
|
18
|
+
/* Added top and bottom margin for better spacing */
|
14
19
|
padding: 20px;
|
15
|
-
background-color: #f4f6f9;
|
20
|
+
background-color: #f4f6f9;
|
21
|
+
/* Lighter background color */
|
16
22
|
}
|
23
|
+
|
17
24
|
h1 {
|
18
|
-
color: #34495e;
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
color: #34495e;
|
26
|
+
/* Darker heading color */
|
27
|
+
border-bottom: 3px solid #3498db;
|
28
|
+
/* Thicker border */
|
29
|
+
padding-bottom: 12px;
|
30
|
+
/* Increased padding */
|
31
|
+
letter-spacing: -0.5px;
|
32
|
+
/* Slightly tighter letter spacing for headings */
|
22
33
|
}
|
34
|
+
|
23
35
|
h2 {
|
24
|
-
color: #3498db;
|
25
|
-
|
26
|
-
margin-
|
36
|
+
color: #3498db;
|
37
|
+
/* Primary blue color for subheadings */
|
38
|
+
margin-top: 35px;
|
39
|
+
/* Increased top margin */
|
40
|
+
margin-bottom: 10px;
|
41
|
+
/* Added bottom margin */
|
27
42
|
}
|
43
|
+
|
28
44
|
h3 {
|
29
|
-
color: #2ecc71;
|
45
|
+
color: #2ecc71;
|
46
|
+
/* Vibrant green for section titles */
|
30
47
|
margin-top: 30px;
|
31
48
|
margin-bottom: 8px;
|
32
49
|
}
|
50
|
+
|
33
51
|
h4 {
|
34
|
-
color: #34495e;
|
52
|
+
color: #34495e;
|
53
|
+
/* Darker color for sub-subheadings */
|
35
54
|
margin-top: 25px;
|
36
55
|
margin-bottom: 5px;
|
37
56
|
}
|
57
|
+
|
38
58
|
p {
|
39
|
-
margin-bottom: 15px;
|
40
|
-
|
59
|
+
margin-bottom: 15px;
|
60
|
+
/* Increased paragraph spacing */
|
61
|
+
color: #555;
|
62
|
+
/* Slightly softer paragraph text color */
|
41
63
|
}
|
42
|
-
|
64
|
+
|
65
|
+
ul,
|
66
|
+
ol {
|
43
67
|
margin-bottom: 15px;
|
44
68
|
color: #555;
|
45
69
|
}
|
70
|
+
|
46
71
|
pre {
|
47
|
-
background-color: #f0f0f0;
|
48
|
-
|
49
|
-
border
|
50
|
-
|
72
|
+
background-color: #f0f0f0;
|
73
|
+
/* Slightly darker pre background */
|
74
|
+
border: 1px solid #ccc;
|
75
|
+
/* Lighter border */
|
76
|
+
border-left: 5px solid #3498db;
|
77
|
+
/* Thicker, more prominent left border */
|
78
|
+
padding: 16px;
|
79
|
+
/* Increased padding */
|
51
80
|
overflow-x: auto;
|
52
|
-
border-radius: 6px;
|
53
|
-
|
81
|
+
border-radius: 6px;
|
82
|
+
/* More rounded corners */
|
83
|
+
font-size: 0.95em;
|
84
|
+
/* Slightly smaller font size in code blocks */
|
54
85
|
}
|
86
|
+
|
55
87
|
code {
|
56
88
|
font-family: 'Courier New', Courier, monospace;
|
57
|
-
color: #2c3e50;
|
89
|
+
color: #2c3e50;
|
90
|
+
/* Darker code text color */
|
58
91
|
}
|
92
|
+
|
59
93
|
.container {
|
60
94
|
background-color: #fff;
|
61
|
-
border-radius: 10px;
|
62
|
-
|
63
|
-
|
95
|
+
border-radius: 10px;
|
96
|
+
/* More rounded container corners */
|
97
|
+
box-shadow: 0 3px 20px rgba(0, 0, 0, 0.08);
|
98
|
+
/* Softer, more subtle shadow */
|
99
|
+
padding: 40px;
|
100
|
+
/* Increased container padding */
|
64
101
|
}
|
102
|
+
|
65
103
|
.feature {
|
66
|
-
margin: 25px 0;
|
67
|
-
|
68
|
-
|
104
|
+
margin: 25px 0;
|
105
|
+
/* Increased feature margin */
|
106
|
+
padding-left: 25px;
|
107
|
+
/* Increased padding */
|
108
|
+
border-left: 5px solid #2ecc71;
|
109
|
+
/* Thicker feature border */
|
69
110
|
}
|
111
|
+
|
70
112
|
.security-feature {
|
71
113
|
background-color: #e8f4fc;
|
72
|
-
padding: 20px;
|
73
|
-
|
74
|
-
|
114
|
+
padding: 20px;
|
115
|
+
/* Increased padding */
|
116
|
+
margin: 15px 0;
|
117
|
+
/* Increased margin */
|
118
|
+
border-radius: 8px;
|
119
|
+
/* More rounded corners */
|
75
120
|
}
|
121
|
+
|
76
122
|
.security-feature ul li {
|
77
|
-
margin-bottom: 8px;
|
123
|
+
margin-bottom: 8px;
|
124
|
+
/* Spacing in security feature lists */
|
78
125
|
}
|
126
|
+
|
79
127
|
.cli-example {
|
80
128
|
background-color: #2c3e50;
|
81
129
|
color: #ecf0f1;
|
82
|
-
padding: 15px 20px;
|
83
|
-
|
84
|
-
|
130
|
+
padding: 15px 20px;
|
131
|
+
/* Increased padding */
|
132
|
+
margin: 15px 0;
|
133
|
+
/* Increased margin */
|
134
|
+
border-radius: 8px;
|
135
|
+
/* More rounded corners */
|
85
136
|
font-family: 'Courier New', Courier, monospace;
|
86
137
|
position: relative;
|
87
|
-
font-size: 0.95em;
|
138
|
+
font-size: 0.95em;
|
139
|
+
/* Slightly smaller font size in CLI examples */
|
88
140
|
}
|
141
|
+
|
89
142
|
.cli-example::before {
|
90
143
|
content: "$";
|
91
144
|
color: #3498db;
|
92
|
-
margin-right: 12px;
|
145
|
+
margin-right: 12px;
|
146
|
+
/* Increased margin */
|
93
147
|
font-weight: bold;
|
94
|
-
display: inline-block;
|
95
|
-
|
96
|
-
|
148
|
+
display: inline-block;
|
149
|
+
/* Ensure proper spacing */
|
150
|
+
width: 15px;
|
151
|
+
/* Fixed width for the dollar sign to align commands */
|
152
|
+
text-align: right;
|
153
|
+
/* Align dollar sign to the right */
|
97
154
|
}
|
155
|
+
|
98
156
|
.cli-section {
|
99
|
-
margin-bottom: 40px;
|
157
|
+
margin-bottom: 40px;
|
158
|
+
/* Increased bottom margin */
|
100
159
|
background-color: #f8f9fa;
|
101
|
-
padding: 25px;
|
102
|
-
|
160
|
+
padding: 25px;
|
161
|
+
/* Increased padding */
|
162
|
+
border-radius: 8px;
|
163
|
+
/* More rounded corners */
|
103
164
|
}
|
165
|
+
|
104
166
|
.output-example {
|
105
167
|
background-color: #f0f0f0;
|
106
|
-
padding: 15px;
|
107
|
-
|
108
|
-
|
168
|
+
padding: 15px;
|
169
|
+
/* Increased padding */
|
170
|
+
margin: 15px 0;
|
171
|
+
/* Increased margin */
|
172
|
+
border-radius: 8px;
|
173
|
+
/* More rounded corners */
|
109
174
|
font-family: 'Courier New', Courier, monospace;
|
110
175
|
font-size: 0.9em;
|
111
|
-
border-left: 5px solid #9b59b6;
|
176
|
+
border-left: 5px solid #9b59b6;
|
177
|
+
/* Thicker border */
|
112
178
|
}
|
179
|
+
|
113
180
|
.tab-container {
|
114
181
|
border: 1px solid #ddd;
|
115
|
-
border-radius: 8px;
|
182
|
+
border-radius: 8px;
|
183
|
+
/* More rounded corners */
|
116
184
|
overflow: hidden;
|
117
|
-
margin: 25px 0;
|
185
|
+
margin: 25px 0;
|
186
|
+
/* Increased margin */
|
118
187
|
}
|
188
|
+
|
119
189
|
.tab-buttons {
|
120
190
|
display: flex;
|
121
191
|
background-color: #f5f5f5;
|
122
|
-
border-bottom: 1px solid #ddd;
|
192
|
+
border-bottom: 1px solid #ddd;
|
193
|
+
/* Added bottom border to tab buttons container */
|
123
194
|
}
|
195
|
+
|
124
196
|
.tab-button {
|
125
|
-
padding: 12px 25px;
|
197
|
+
padding: 12px 25px;
|
198
|
+
/* Increased padding */
|
126
199
|
background-color: transparent;
|
127
200
|
border: none;
|
128
201
|
cursor: pointer;
|
129
|
-
border-right: none;
|
202
|
+
border-right: none;
|
203
|
+
/* Removed right border */
|
130
204
|
transition: background-color 0.3s;
|
131
|
-
font-weight: 500;
|
132
|
-
|
205
|
+
font-weight: 500;
|
206
|
+
/* Slightly bolder tab button text */
|
207
|
+
color: #777;
|
208
|
+
/* Slightly muted tab button text color */
|
133
209
|
}
|
210
|
+
|
134
211
|
.tab-button:hover {
|
135
|
-
background-color: #f0f0f0;
|
136
|
-
|
212
|
+
background-color: #f0f0f0;
|
213
|
+
/* Lighter hover background */
|
214
|
+
color: #555;
|
215
|
+
/* Darker hover text color */
|
137
216
|
}
|
217
|
+
|
138
218
|
.tab-button.active {
|
139
|
-
background-color: #fff;
|
140
|
-
|
141
|
-
|
142
|
-
|
219
|
+
background-color: #fff;
|
220
|
+
/* White background for active tab */
|
221
|
+
border-bottom: 3px solid #3498db;
|
222
|
+
/* Underline for active tab */
|
223
|
+
color: #34495e;
|
224
|
+
/* Darker text for active tab */
|
225
|
+
font-weight: bold;
|
226
|
+
/* Bold text for active tab */
|
143
227
|
}
|
228
|
+
|
144
229
|
.tab-content {
|
145
230
|
display: none;
|
146
|
-
padding: 20px;
|
147
|
-
|
231
|
+
padding: 20px;
|
232
|
+
/* Increased padding */
|
233
|
+
background-color: #fff;
|
234
|
+
/* White background for tab content */
|
148
235
|
}
|
236
|
+
|
149
237
|
.tab-content.active {
|
150
238
|
display: block;
|
151
239
|
}
|
240
|
+
|
152
241
|
.badge {
|
153
242
|
display: inline-block;
|
154
|
-
padding: 4px 10px;
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
243
|
+
padding: 4px 10px;
|
244
|
+
/* Increased badge padding */
|
245
|
+
border-radius: 6px;
|
246
|
+
/* More rounded corners */
|
247
|
+
font-size: 13px;
|
248
|
+
/* Slightly larger font size */
|
249
|
+
font-weight: 600;
|
250
|
+
/* Bolder badge text */
|
251
|
+
letter-spacing: 0.5px;
|
252
|
+
/* Added letter spacing */
|
159
253
|
}
|
254
|
+
|
160
255
|
.badge-new {
|
161
256
|
background-color: #2ecc71;
|
162
257
|
color: white;
|
163
258
|
}
|
259
|
+
|
164
260
|
.note {
|
165
261
|
background-color: #fff8e1;
|
166
|
-
padding: 15px;
|
167
|
-
|
168
|
-
|
169
|
-
|
262
|
+
padding: 15px;
|
263
|
+
/* Increased padding */
|
264
|
+
border-left: 5px solid #ffc107;
|
265
|
+
/* Thicker border */
|
266
|
+
margin: 15px 0;
|
267
|
+
/* Increased margin */
|
268
|
+
border-radius: 6px;
|
269
|
+
/* More rounded corners */
|
170
270
|
}
|
271
|
+
|
171
272
|
.note strong {
|
172
273
|
font-weight: bold;
|
173
|
-
color: #333;
|
274
|
+
color: #333;
|
275
|
+
/* Make "Note:" bold and slightly darker */
|
174
276
|
}
|
277
|
+
|
175
278
|
footer {
|
176
|
-
margin-top: 50px;
|
279
|
+
margin-top: 50px;
|
280
|
+
/* Increased footer margin */
|
177
281
|
text-align: center;
|
178
282
|
color: #7f8c8d;
|
179
283
|
padding-top: 20px;
|
180
|
-
border-top: 1px solid #ddd;
|
284
|
+
border-top: 1px solid #ddd;
|
285
|
+
/* Added top border to footer */
|
181
286
|
}
|
287
|
+
|
182
288
|
footer p {
|
183
|
-
color: #95a5a6;
|
184
|
-
|
289
|
+
color: #95a5a6;
|
290
|
+
/* Softer footer text color */
|
291
|
+
font-size: 0.9em;
|
292
|
+
/* Smaller footer font size */
|
185
293
|
}
|
186
294
|
</style>
|
187
295
|
</head>
|
296
|
+
|
188
297
|
<body>
|
189
298
|
<div class="container">
|
190
299
|
<h1>Lanet</h1>
|
191
|
-
<p>A secure network communication library that enables reliable and protected message exchange between devices
|
300
|
+
<p>A secure network communication library that enables reliable and protected message exchange between devices
|
301
|
+
on the same network.</p>
|
192
302
|
|
193
303
|
<h2>Key Features</h2>
|
194
304
|
|
@@ -205,9 +315,11 @@
|
|
205
315
|
<h4>Benefits of Digital Signatures:</h4>
|
206
316
|
<ul>
|
207
317
|
<li><strong>Authentication</strong>: Verify that the message came from the claimed sender</li>
|
208
|
-
<li><strong>Data Integrity</strong>: Ensure the message hasn't been tampered with during transit
|
318
|
+
<li><strong>Data Integrity</strong>: Ensure the message hasn't been tampered with during transit
|
319
|
+
</li>
|
209
320
|
<li><strong>Non-repudiation</strong>: Senders cannot deny sending a message they signed</li>
|
210
|
-
<li><strong>Protection against MITM attacks</strong>: Detect man-in-the-middle tampering attempts
|
321
|
+
<li><strong>Protection against MITM attacks</strong>: Detect man-in-the-middle tampering attempts
|
322
|
+
</li>
|
211
323
|
</ul>
|
212
324
|
</div>
|
213
325
|
</div>
|
@@ -224,13 +336,15 @@
|
|
224
336
|
|
225
337
|
<div class="feature">
|
226
338
|
<h3>File Transfer <span class="badge badge-new">New in v0.3.0</span></h3>
|
227
|
-
<p>Securely transfer files between devices with encryption, digital signatures, and integrity verification
|
339
|
+
<p>Securely transfer files between devices with encryption, digital signatures, and integrity verification.
|
340
|
+
</p>
|
228
341
|
</div>
|
229
342
|
|
230
343
|
<div class="feature">
|
231
344
|
<h3>Mesh Networking <span class="badge badge-new">New in v0.4.0</span></h3>
|
232
|
-
<p>Create resilient, decentralized mesh networks that enable communication between devices even without
|
233
|
-
|
345
|
+
<p>Create resilient, decentralized mesh networks that enable communication between devices even without
|
346
|
+
direct connectivity.</p>
|
347
|
+
|
234
348
|
<div class="security-feature">
|
235
349
|
<h4>Benefits of Mesh Networking:</h4>
|
236
350
|
<ul>
|
@@ -244,17 +358,24 @@
|
|
244
358
|
</div>
|
245
359
|
|
246
360
|
<div class="feature">
|
247
|
-
<h3>Advanced Traceroute <span class="badge badge-new">New in v0.5.
|
248
|
-
<p>Analyze network paths with multi-protocol traceroute capabilities to understand connectivity and
|
249
|
-
|
361
|
+
<h3>Advanced Traceroute <span class="badge badge-new">New in v0.5.1</span></h3>
|
362
|
+
<p>Analyze network paths with multi-protocol traceroute capabilities to understand connectivity and
|
363
|
+
troubleshoot network issues.</p>
|
364
|
+
|
250
365
|
<div class="security-feature">
|
251
366
|
<h4>Features of Advanced Traceroute:</h4>
|
252
367
|
<ul>
|
253
|
-
<li><strong>Multi-protocol support</strong>: Use ICMP, UDP, or TCP protocols for different network
|
254
|
-
|
368
|
+
<li><strong>Multi-protocol support</strong>: Use ICMP, UDP, or TCP protocols for different network
|
369
|
+
environments</li>
|
370
|
+
<li><strong>Load balancing detection</strong>: Identify multi-path routing and load balancers in the
|
371
|
+
network</li>
|
255
372
|
<li><strong>Response time analysis</strong>: Measure latency at each hop in the network path</li>
|
256
|
-
<li><strong>Customizable parameters</strong>: Adjust max hops, timeouts, and query count for
|
257
|
-
|
373
|
+
<li><strong>Customizable parameters</strong>: Adjust max hops, timeouts, and query count for
|
374
|
+
different scenarios</li>
|
375
|
+
<li><strong>Hostname resolution</strong>: Automatically resolve IP addresses to hostnames for easier
|
376
|
+
identification</li>
|
377
|
+
<li><strong>Fallback mechanism</strong>: Automatically uses system traceroute when elevated
|
378
|
+
permissions aren't available</li>
|
258
379
|
</ul>
|
259
380
|
</div>
|
260
381
|
</div>
|
@@ -262,7 +383,8 @@
|
|
262
383
|
<h2>Command Line Interface</h2>
|
263
384
|
|
264
385
|
<div class="note">
|
265
|
-
<strong>Note:</strong> All Lanet commands have detailed help available. Try
|
386
|
+
<strong>Note:</strong> All Lanet commands have detailed help available. Try
|
387
|
+
<code>lanet [command] --help</code> for more options.
|
266
388
|
</div>
|
267
389
|
|
268
390
|
<div class="cli-section">
|
@@ -280,12 +402,12 @@
|
|
280
402
|
</div>
|
281
403
|
|
282
404
|
<div class="output-example">
|
283
|
-
Key pair generated!
|
284
|
-
Private key saved to: /home/user/.lanet_keys/lanet_private.key
|
285
|
-
Public key saved to: /home/user/.lanet_keys/lanet_public.key
|
405
|
+
Key pair generated!
|
406
|
+
Private key saved to: /home/user/.lanet_keys/lanet_private.key
|
407
|
+
Public key saved to: /home/user/.lanet_keys/lanet_public.key
|
286
408
|
|
287
|
-
IMPORTANT: Keep your private key secure and never share it.
|
288
|
-
Share your public key with others who need to verify your messages.
|
409
|
+
IMPORTANT: Keep your private key secure and never share it.
|
410
|
+
Share your public key with others who need to verify your messages.
|
289
411
|
</div>
|
290
412
|
|
291
413
|
<h4>Send a Signed Message</h4>
|
@@ -295,7 +417,8 @@ Share your public key with others who need to verify your messages.
|
|
295
417
|
|
296
418
|
<h4>Send a Signed & Encrypted Message</h4>
|
297
419
|
<div class="cli-example">
|
298
|
-
lanet send --target 192.168.1.5 --message "Secure signed message" --key "my_secret_key"
|
420
|
+
lanet send --target 192.168.1.5 --message "Secure signed message" --key "my_secret_key"
|
421
|
+
--private-key-file lanet_private.key
|
299
422
|
</div>
|
300
423
|
|
301
424
|
<h4>Broadcast a Signed Message</h4>
|
@@ -315,10 +438,10 @@ Share your public key with others who need to verify your messages.
|
|
315
438
|
|
316
439
|
<p>Example output when receiving a signed message:</p>
|
317
440
|
<div class="output-example">
|
318
|
-
Message from 192.168.1.5:
|
319
|
-
Content: Hello, this is a signed message
|
320
|
-
Signature: ✓ VERIFIED
|
321
|
-
----------------------------------------
|
441
|
+
Message from 192.168.1.5:
|
442
|
+
Content: Hello, this is a signed message
|
443
|
+
Signature: ✓ VERIFIED
|
444
|
+
----------------------------------------
|
322
445
|
</div>
|
323
446
|
</div>
|
324
447
|
|
@@ -391,7 +514,8 @@ Signature: ✓ VERIFIED
|
|
391
514
|
|
392
515
|
<p>Send a file with encryption and digital signature:</p>
|
393
516
|
<div class="cli-example">
|
394
|
-
lanet send-file --target 192.168.1.5 --file document.pdf --key "my_secret_key" --private-key-file
|
517
|
+
lanet send-file --target 192.168.1.5 --file document.pdf --key "my_secret_key" --private-key-file
|
518
|
+
lanet_private.key
|
395
519
|
</div>
|
396
520
|
|
397
521
|
<h4>Receive Files</h4>
|
@@ -401,15 +525,16 @@ Signature: ✓ VERIFIED
|
|
401
525
|
|
402
526
|
<p>With signature verification:</p>
|
403
527
|
<div class="cli-example">
|
404
|
-
lanet receive-file --output ./downloads --encryption-key "my_secret_key" --public-key-file
|
528
|
+
lanet receive-file --output ./downloads --encryption-key "my_secret_key" --public-key-file
|
529
|
+
lanet_public.key
|
405
530
|
</div>
|
406
531
|
|
407
532
|
<p>Example output during file transfer:</p>
|
408
533
|
<div class="output-example">
|
409
|
-
Receiving file: document.pdf from 192.168.1.5
|
410
|
-
Size: 1048576 bytes
|
411
|
-
Transfer ID: 8a7b6c5d-4e3f-2g1h-0i9j-8k7l6m5n4o3p
|
412
|
-
Progress: 75% (786432/1048576 bytes)
|
534
|
+
Receiving file: document.pdf from 192.168.1.5
|
535
|
+
Size: 1048576 bytes
|
536
|
+
Transfer ID: 8a7b6c5d-4e3f-2g1h-0i9j-8k7l6m5n4o3p
|
537
|
+
Progress: 75% (786432/1048576 bytes)
|
413
538
|
</div>
|
414
539
|
</div>
|
415
540
|
|
@@ -443,13 +568,13 @@ Progress: 75% (786432/1048576 bytes)
|
|
443
568
|
|
444
569
|
<p>Example output when viewing mesh info:</p>
|
445
570
|
<div class="output-example">
|
446
|
-
Mesh Node ID: 4f9a8b7c-6d5e-4f3e-2d1c-0b9a8b7c6d5e
|
571
|
+
Mesh Node ID: 4f9a8b7c-6d5e-4f3e-2d1c-0b9a8b7c6d5e
|
447
572
|
|
448
|
-
Connected nodes:
|
449
|
-
|
450
|
-
|
573
|
+
Connected nodes:
|
574
|
+
b1c2d3e4-f5g6-7h8i-9j0k-l1m2n3o4p5q6 (192.168.1.5, last seen 12s ago)
|
575
|
+
c5d4e3f2-g1h0-i9j8-k7l6-m5n4o3p2q1r0 (192.168.1.10, last seen 5s ago)
|
451
576
|
|
452
|
-
Message cache: 24 messages
|
577
|
+
Message cache: 24 messages
|
453
578
|
</div>
|
454
579
|
</div>
|
455
580
|
|
@@ -478,20 +603,20 @@ Message cache: 24 messages
|
|
478
603
|
|
479
604
|
<p>Example output of a traceroute:</p>
|
480
605
|
<div class="output-example">
|
481
|
-
Tracing route to github.com using UDP protocol
|
482
|
-
Maximum hops: 30, Timeout: 1s, Queries: 3
|
483
|
-
======================================================================
|
484
|
-
TTL
|
485
|
-
----------------------------------------------------------------------
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
======================================================================
|
494
|
-
Trace complete.
|
606
|
+
Tracing route to github.com using UDP protocol
|
607
|
+
Maximum hops: 30, Timeout: 1s, Queries: 3
|
608
|
+
======================================================================
|
609
|
+
TTL IP Address Hostname Response Time
|
610
|
+
----------------------------------------------------------------------
|
611
|
+
1 192.168.1.1 router.home 2.34ms
|
612
|
+
2 172.16.42.1 isp-gateway.net 8.72ms
|
613
|
+
3 216.58.223.14 15.35ms
|
614
|
+
4 172.217.170.78 edge-router.google.com 22.89ms
|
615
|
+
5 * * Request timed out
|
616
|
+
6 140.82.121.4 github.com 45.23ms
|
617
|
+
Destination unreachable
|
618
|
+
======================================================================
|
619
|
+
Trace complete.
|
495
620
|
</div>
|
496
621
|
</div>
|
497
622
|
|
@@ -741,10 +866,11 @@ end</code></pre>
|
|
741
866
|
<pre><code>gem install lanet</code></pre>
|
742
867
|
|
743
868
|
<h2>Documentation</h2>
|
744
|
-
<p>For complete documentation, please visit the <a href="https://github.com/davidesantangelo/lanet">GitHub
|
869
|
+
<p>For complete documentation, please visit the <a href="https://github.com/davidesantangelo/lanet">GitHub
|
870
|
+
repository</a>.</p>
|
745
871
|
|
746
872
|
<footer style="margin-top: 40px; text-align: center; color: #7f8c8d;">
|
747
|
-
<p>Lanet v0.5.
|
873
|
+
<p>Lanet v0.5.1 - Secure Network Communications Library</p>
|
748
874
|
</footer>
|
749
875
|
</div>
|
750
876
|
|
@@ -767,4 +893,5 @@ end</code></pre>
|
|
767
893
|
}
|
768
894
|
</script>
|
769
895
|
</body>
|
896
|
+
|
770
897
|
</html>
|
data/lib/lanet/traceroute.rb
CHANGED
@@ -34,14 +34,7 @@ module Lanet
|
|
34
34
|
destination_ip = resolve_destination(destination)
|
35
35
|
|
36
36
|
begin
|
37
|
-
|
38
|
-
when :icmp
|
39
|
-
trace_icmp(destination_ip)
|
40
|
-
when :udp
|
41
|
-
trace_udp(destination_ip)
|
42
|
-
when :tcp
|
43
|
-
trace_tcp(destination_ip)
|
44
|
-
end
|
37
|
+
trace_protocol(destination_ip)
|
45
38
|
rescue StandardError => e
|
46
39
|
raise e unless e.message.include?("Must run as root/administrator")
|
47
40
|
|
@@ -54,15 +47,20 @@ module Lanet
|
|
54
47
|
|
55
48
|
private
|
56
49
|
|
50
|
+
def trace_protocol(destination_ip)
|
51
|
+
case @protocol
|
52
|
+
when :icmp then trace_icmp(destination_ip)
|
53
|
+
when :udp then trace_udp(destination_ip)
|
54
|
+
when :tcp then trace_tcp(destination_ip)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
57
58
|
def trace_using_system_command(destination)
|
58
59
|
# Build the appropriate system traceroute command
|
59
60
|
system_cmd = case @protocol
|
60
|
-
when :icmp
|
61
|
-
|
62
|
-
|
63
|
-
"traceroute -T"
|
64
|
-
else
|
65
|
-
"traceroute" # UDP is the default for most traceroute commands
|
61
|
+
when :icmp then "traceroute -I"
|
62
|
+
when :tcp then "traceroute -T"
|
63
|
+
else "traceroute" # UDP is the default
|
66
64
|
end
|
67
65
|
|
68
66
|
# Add options for max hops, timeout, and queries/retries
|
@@ -90,32 +88,18 @@ module Lanet
|
|
90
88
|
hop_details = Regexp.last_match(2)
|
91
89
|
|
92
90
|
# Parse the hop details
|
93
|
-
hostname = nil
|
94
|
-
avg_time = nil
|
95
|
-
|
96
|
-
# Check for timeout indicated by asterisks
|
97
91
|
if ["* * *", "*"].include?(hop_details.strip)
|
98
92
|
# All timeouts at this hop
|
99
93
|
@results << { ttl: hop_num, ip: nil, hostname: nil, avg_time: nil, timeouts: @queries }
|
100
94
|
next
|
101
95
|
end
|
102
96
|
|
103
|
-
# Extract
|
97
|
+
# Extract IP, hostname, and timing info
|
104
98
|
all_ips = extract_multiple_ips(hop_details)
|
105
|
-
|
106
|
-
# Extract the first IP (primary IP for this hop)
|
107
99
|
ip = all_ips&.first
|
108
|
-
|
109
|
-
# Try to extract hostname if present
|
110
|
-
# Format: "hostname (ip)"
|
111
|
-
if hop_details =~ /([^\s(]+)\s+\(([0-9.]+)\)/
|
112
|
-
hostname = Regexp.last_match(1)
|
113
|
-
# We already have the IP from all_ips, so no need to set it again
|
114
|
-
end
|
115
|
-
|
116
|
-
# Extract response times - typically format is "X.XXX ms Y.YYY ms Z.ZZZ ms"
|
100
|
+
hostname = extract_hostname(hop_details)
|
117
101
|
times = hop_details.scan(/(\d+\.\d+)\s*ms/).flatten.map(&:to_f)
|
118
|
-
avg_time = (times.sum / times.size).round(2)
|
102
|
+
avg_time = times.any? ? (times.sum / times.size).round(2) : nil
|
119
103
|
|
120
104
|
# Add to results
|
121
105
|
@results << {
|
@@ -124,22 +108,22 @@ module Lanet
|
|
124
108
|
hostname: hostname,
|
125
109
|
avg_time: avg_time,
|
126
110
|
timeouts: @queries - times.size,
|
127
|
-
# Include all IPs if there are multiple
|
128
111
|
all_ips: all_ips&.size && all_ips.size > 1 ? all_ips : nil
|
129
112
|
}
|
130
113
|
end
|
131
114
|
end
|
132
115
|
|
116
|
+
def extract_hostname(hop_details)
|
117
|
+
hop_details =~ /([^\s(]+)\s+\(([0-9.]+)\)/ ? Regexp.last_match(1) : nil
|
118
|
+
end
|
119
|
+
|
133
120
|
def extract_multiple_ips(hop_details)
|
134
121
|
# Match all IP addresses in the hop details
|
135
122
|
ips = hop_details.scan(/\b(?:\d{1,3}\.){3}\d{1,3}\b/).uniq
|
136
123
|
|
137
|
-
# If no IPs were found in a non-timeout line,
|
124
|
+
# If no IPs were found in a non-timeout line, try alternate format
|
138
125
|
if ips.empty? && !hop_details.include?("*")
|
139
|
-
|
140
|
-
potential_ips = hop_details.split(/\s+/).select do |part|
|
141
|
-
part =~ /\b(?:\d{1,3}\.){3}\d{1,3}\b/
|
142
|
-
end
|
126
|
+
potential_ips = hop_details.split(/\s+/).select { |part| part =~ /\b(?:\d{1,3}\.){3}\d{1,3}\b/ }
|
143
127
|
ips = potential_ips unless potential_ips.empty?
|
144
128
|
end
|
145
129
|
|
@@ -153,14 +137,10 @@ module Lanet
|
|
153
137
|
# Otherwise, resolve the hostname to an IPv4 address
|
154
138
|
begin
|
155
139
|
addresses = Resolv.getaddresses(destination)
|
156
|
-
|
157
|
-
# If no addresses are returned, the hostname is unresolvable
|
158
140
|
raise Resolv::ResolvError, "no address for #{destination}" if addresses.empty?
|
159
141
|
|
160
142
|
# Find the first IPv4 address
|
161
143
|
ipv4_address = addresses.find { |addr| addr =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ }
|
162
|
-
|
163
|
-
# If no IPv4 address is found, raise an error
|
164
144
|
raise "No IPv4 address found for hostname: #{destination}" if ipv4_address.nil?
|
165
145
|
|
166
146
|
ipv4_address
|
@@ -181,10 +161,8 @@ module Lanet
|
|
181
161
|
hop_info = trace_hop_icmp(destination_ip, ttl)
|
182
162
|
@results << hop_info
|
183
163
|
|
184
|
-
# Stop if we've reached the destination
|
185
|
-
break if hop_info[:ip] == destination_ip
|
186
|
-
# Stop if we've hit an unreachable marker
|
187
|
-
break if hop_info[:unreachable]
|
164
|
+
# Stop if we've reached the destination or hit unreachable
|
165
|
+
break if hop_info[:ip] == destination_ip || hop_info[:unreachable]
|
188
166
|
end
|
189
167
|
end
|
190
168
|
|
@@ -193,9 +171,7 @@ module Lanet
|
|
193
171
|
|
194
172
|
# Use ping with increasing TTL values
|
195
173
|
@queries.times do
|
196
|
-
Time.now
|
197
174
|
cmd = ping_command_with_ttl(destination_ip, ttl)
|
198
|
-
|
199
175
|
ip = nil
|
200
176
|
response_time = nil
|
201
177
|
|
@@ -246,8 +222,6 @@ module Lanet
|
|
246
222
|
|
247
223
|
def trace_hop_udp(destination_ip, ttl)
|
248
224
|
hop_info = { ttl: ttl, responses: [] }
|
249
|
-
|
250
|
-
# Create a listener socket for ICMP responses
|
251
225
|
icmp_socket = create_icmp_socket
|
252
226
|
|
253
227
|
@queries.times do |i|
|
@@ -295,25 +269,23 @@ module Lanet
|
|
295
269
|
|
296
270
|
def create_icmp_socket
|
297
271
|
socket = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_ICMP)
|
298
|
-
|
299
|
-
# Windows requires different socket setup
|
300
|
-
else
|
301
|
-
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
302
|
-
end
|
272
|
+
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true) unless windows?
|
303
273
|
socket
|
304
274
|
rescue Errno::EPERM, Errno::EACCES
|
305
275
|
raise "Must run as root/administrator to create raw sockets for traceroute"
|
306
276
|
end
|
307
277
|
|
278
|
+
def windows?
|
279
|
+
RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
|
280
|
+
end
|
281
|
+
|
308
282
|
def trace_tcp(destination_ip)
|
309
283
|
1.upto(@max_hops) do |ttl|
|
310
284
|
hop_info = trace_hop_tcp(destination_ip, ttl)
|
311
285
|
@results << hop_info
|
312
286
|
|
313
|
-
# Stop if we've reached the destination
|
314
|
-
break if hop_info[:ip] == destination_ip
|
315
|
-
# Stop if we've hit an unreachable marker
|
316
|
-
break if hop_info[:unreachable]
|
287
|
+
# Stop if we've reached the destination or hit unreachable
|
288
|
+
break if hop_info[:ip] == destination_ip || hop_info[:unreachable]
|
317
289
|
end
|
318
290
|
end
|
319
291
|
|
@@ -324,15 +296,16 @@ module Lanet
|
|
324
296
|
# Use different ports for each query
|
325
297
|
port = 80 + i
|
326
298
|
start_time = Time.now
|
299
|
+
socket = nil
|
327
300
|
|
328
301
|
begin
|
329
302
|
# Create TCP socket with specific TTL
|
330
303
|
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
331
304
|
socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, ttl)
|
305
|
+
sockaddr = Socket.sockaddr_in(port, destination_ip)
|
332
306
|
|
333
307
|
# Attempt to connect with timeout
|
334
308
|
Timeout.timeout(@timeout) do
|
335
|
-
sockaddr = Socket.sockaddr_in(port, destination_ip)
|
336
309
|
socket.connect_nonblock(sockaddr)
|
337
310
|
end
|
338
311
|
|
@@ -345,39 +318,7 @@ module Lanet
|
|
345
318
|
}
|
346
319
|
rescue IO::WaitWritable
|
347
320
|
# Connection in progress - need to use select for non-blocking socket
|
348
|
-
|
349
|
-
ip = nil
|
350
|
-
|
351
|
-
begin
|
352
|
-
Timeout.timeout(@timeout) do
|
353
|
-
_, writable, = IO.select(nil, [socket], nil, @timeout)
|
354
|
-
if writable&.any?
|
355
|
-
# Socket is writable, check for errors
|
356
|
-
begin
|
357
|
-
socket.connect_nonblock(sockaddr) # Will raise Errno::EISCONN if connected
|
358
|
-
rescue Errno::EISCONN
|
359
|
-
# Successfully connected
|
360
|
-
response_time = ((Time.now - start_time) * 1000).round(2)
|
361
|
-
ip = destination_ip
|
362
|
-
rescue SystemCallError
|
363
|
-
# Get the intermediary IP from the error
|
364
|
-
# This is a simplification - in reality, we'd need to use raw sockets
|
365
|
-
# and analyze TCP packets with specific TTL values
|
366
|
-
ip = nil
|
367
|
-
end
|
368
|
-
end
|
369
|
-
end
|
370
|
-
rescue Timeout::Error
|
371
|
-
hop_info[:responses] << { ip: nil, response_time: nil, timeout: true }
|
372
|
-
end
|
373
|
-
|
374
|
-
if ip
|
375
|
-
hop_info[:responses] << {
|
376
|
-
ip: ip,
|
377
|
-
response_time: response_time,
|
378
|
-
timeout: false
|
379
|
-
}
|
380
|
-
end
|
321
|
+
handle_wait_writable(socket, sockaddr, start_time, destination_ip, hop_info)
|
381
322
|
rescue SystemCallError, Timeout::Error
|
382
323
|
hop_info[:responses] << { ip: nil, response_time: nil, timeout: true }
|
383
324
|
ensure
|
@@ -388,6 +329,39 @@ module Lanet
|
|
388
329
|
process_hop_responses(hop_info)
|
389
330
|
end
|
390
331
|
|
332
|
+
def handle_wait_writable(socket, sockaddr, start_time, destination_ip, hop_info)
|
333
|
+
response_time = nil
|
334
|
+
ip = nil
|
335
|
+
|
336
|
+
begin
|
337
|
+
Timeout.timeout(@timeout) do
|
338
|
+
_, writable, = IO.select(nil, [socket], nil, @timeout)
|
339
|
+
if writable&.any?
|
340
|
+
begin
|
341
|
+
socket.connect_nonblock(sockaddr) # Will raise Errno::EISCONN if connected
|
342
|
+
rescue Errno::EISCONN
|
343
|
+
# Successfully connected
|
344
|
+
response_time = ((Time.now - start_time) * 1000).round(2)
|
345
|
+
ip = destination_ip
|
346
|
+
rescue SystemCallError
|
347
|
+
# Get the intermediary IP from the error - would need raw sockets to do properly
|
348
|
+
ip = nil
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
rescue Timeout::Error
|
353
|
+
hop_info[:responses] << { ip: nil, response_time: nil, timeout: true }
|
354
|
+
end
|
355
|
+
|
356
|
+
return unless ip
|
357
|
+
|
358
|
+
hop_info[:responses] << {
|
359
|
+
ip: ip,
|
360
|
+
response_time: response_time,
|
361
|
+
timeout: false
|
362
|
+
}
|
363
|
+
end
|
364
|
+
|
391
365
|
def process_hop_responses(hop_info)
|
392
366
|
# Count timeouts
|
393
367
|
timeouts = hop_info[:responses].count { |r| r[:timeout] }
|
data/lib/lanet/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lanet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davide Santangelo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-03-
|
11
|
+
date: 2025-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|