mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-01 13:17:21 +02:00
Fixed #342
- Added port scanner - Moved handlers for IP scanner into ipscan module -Minor code optimization
This commit is contained in:
parent
528be69fe0
commit
99295cad86
@ -8,6 +8,7 @@ import (
|
||||
"imuslab.com/zoraxy/mod/acme/acmedns"
|
||||
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
||||
"imuslab.com/zoraxy/mod/auth"
|
||||
"imuslab.com/zoraxy/mod/ipscan"
|
||||
"imuslab.com/zoraxy/mod/netstat"
|
||||
"imuslab.com/zoraxy/mod/netutils"
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
@ -187,7 +188,8 @@ func initAPIs(targetMux *http.ServeMux) {
|
||||
authRouter.HandleFunc("/api/analytic/resetRange", AnalyticLoader.HandleRangeReset)
|
||||
|
||||
//Network utilities
|
||||
authRouter.HandleFunc("/api/tools/ipscan", HandleIpScan)
|
||||
authRouter.HandleFunc("/api/tools/ipscan", ipscan.HandleIpScan)
|
||||
authRouter.HandleFunc("/api/tools/portscan", ipscan.HandleScanPort)
|
||||
authRouter.HandleFunc("/api/tools/traceroute", netutils.HandleTraceRoute)
|
||||
authRouter.HandleFunc("/api/tools/ping", netutils.HandlePing)
|
||||
authRouter.HandleFunc("/api/tools/whois", netutils.HandleWhois)
|
||||
|
79
src/mod/ipscan/handlers.go
Normal file
79
src/mod/ipscan/handlers.go
Normal file
@ -0,0 +1,79 @@
|
||||
package ipscan
|
||||
|
||||
/*
|
||||
ipscan http handlers
|
||||
|
||||
This script provide http handlers for ipscan module
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
)
|
||||
|
||||
// HandleScanPort is the HTTP handler for scanning opened ports on a given IP address
|
||||
func HandleScanPort(w http.ResponseWriter, r *http.Request) {
|
||||
targetIp, err := utils.GetPara(r, "ip")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "target IP address not given")
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the IP is a valid IP address
|
||||
ip := net.ParseIP(targetIp)
|
||||
if ip == nil {
|
||||
utils.SendErrorResponse(w, "invalid IP address")
|
||||
return
|
||||
}
|
||||
|
||||
// Scan the ports
|
||||
openPorts := ScanPorts(targetIp)
|
||||
jsonData, err := json.Marshal(openPorts)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "failed to marshal JSON")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SendJSONResponse(w, string(jsonData))
|
||||
}
|
||||
|
||||
// HandleIpScan is the HTTP handler for scanning IP addresses in a given range or CIDR
|
||||
func HandleIpScan(w http.ResponseWriter, r *http.Request) {
|
||||
cidr, err := utils.PostPara(r, "cidr")
|
||||
if err != nil {
|
||||
//Ip range mode
|
||||
start, err := utils.PostPara(r, "start")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "missing start ip")
|
||||
return
|
||||
}
|
||||
|
||||
end, err := utils.PostPara(r, "end")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "missing end ip")
|
||||
return
|
||||
}
|
||||
|
||||
discoveredHosts, err := ScanIpRange(start, end)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
js, _ := json.Marshal(discoveredHosts)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else {
|
||||
//CIDR mode
|
||||
discoveredHosts, err := ScanCIDRRange(cidr)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
js, _ := json.Marshal(discoveredHosts)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ type DiscoveredHost struct {
|
||||
HttpsPortDetected bool
|
||||
}
|
||||
|
||||
//Scan an IP range given the start and ending ip address
|
||||
// Scan an IP range given the start and ending ip address
|
||||
func ScanIpRange(start, end string) ([]*DiscoveredHost, error) {
|
||||
ipStart := net.ParseIP(start)
|
||||
ipEnd := net.ParseIP(end)
|
||||
@ -57,7 +57,6 @@ func ScanIpRange(start, end string) ([]*DiscoveredHost, error) {
|
||||
host.CheckHostname()
|
||||
host.CheckPort("http", 80, &host.HttpPortDetected)
|
||||
host.CheckPort("https", 443, &host.HttpsPortDetected)
|
||||
fmt.Println("OK", host)
|
||||
hosts = append(hosts, host)
|
||||
|
||||
}(thisIp)
|
||||
@ -118,7 +117,7 @@ func (host *DiscoveredHost) CheckPing() error {
|
||||
func (host *DiscoveredHost) CheckHostname() {
|
||||
// lookup the hostname for the IP address
|
||||
names, err := net.LookupAddr(host.IP)
|
||||
fmt.Println(names, err)
|
||||
//fmt.Println(names, err)
|
||||
if err == nil && len(names) > 0 {
|
||||
host.Hostname = names[0]
|
||||
}
|
||||
|
48
src/mod/ipscan/portscan.go
Normal file
48
src/mod/ipscan/portscan.go
Normal file
@ -0,0 +1,48 @@
|
||||
package ipscan
|
||||
|
||||
/*
|
||||
Port Scanner
|
||||
|
||||
This module scan the given IP address and scan all the opened port
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// OpenedPort holds information about an open port and its service type
|
||||
type OpenedPort struct {
|
||||
Port int
|
||||
IsTCP bool
|
||||
}
|
||||
|
||||
// ScanPorts scans all the opened ports on a given host IP (both IPv4 and IPv6)
|
||||
func ScanPorts(host string) []*OpenedPort {
|
||||
var openPorts []*OpenedPort
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
|
||||
for port := 1; port <= 65535; port++ {
|
||||
wg.Add(1)
|
||||
go func(port int) {
|
||||
defer wg.Done()
|
||||
address := fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
// Check TCP
|
||||
conn, err := net.DialTimeout("tcp", address, 5*time.Second)
|
||||
if err == nil {
|
||||
mu.Lock()
|
||||
openPorts = append(openPorts, &OpenedPort{Port: port, IsTCP: true})
|
||||
mu.Unlock()
|
||||
conn.Close()
|
||||
}
|
||||
}(port)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return openPorts
|
||||
}
|
@ -17,10 +17,21 @@
|
||||
<p>Discover mDNS enabled service in this gateway forwarded network</p>
|
||||
<button class="ui basic larger circular button" onclick="launchToolWithSize('./tools/mdns.html',1000, 640);">View Discovery</button>
|
||||
<div class="ui divider"></div>
|
||||
<!-- IP Scanner-->
|
||||
<h2>IP Scanner</h2>
|
||||
<p>Discover local area network devices by pinging them one by one</p>
|
||||
<button class="ui basic larger circular button" onclick="launchToolWithSize('./tools/ipscan.html',1000, 640);">Start Scanner</button>
|
||||
<div class="ui stackable grid">
|
||||
<div class="eight wide column">
|
||||
<!-- IP Scanner-->
|
||||
<h2>IP Scanner</h2>
|
||||
<p>Discover local area network devices by pinging them one by one</p>
|
||||
<button class="ui basic larger circular button" onclick="launchToolWithSize('./tools/ipscan.html',1000, 640);">Start Scanner</button>
|
||||
</div>
|
||||
<div class="eight wide column">
|
||||
<!-- Port Scanner-->
|
||||
<h2>Port Scanner</h2>
|
||||
<p>Scan for open ports on a given IP address</p>
|
||||
<button class="ui basic larger circular button" onclick="launchToolWithSize('./tools/portscan.html',1000, 640);">Start Scanner</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
<!-- Traceroute-->
|
||||
<h2>Traceroute / Ping</h2>
|
||||
|
@ -10,7 +10,6 @@
|
||||
<title>IP Scanner | Zoraxy</title>
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../../script/ao_module.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
@ -149,13 +148,23 @@
|
||||
|
||||
function displayResults(data) {
|
||||
var table = $('<table class="ui celled unstackable table"></table>');
|
||||
var header = $('<thead><tr><th>IP Address</th><th>Ping</th><th>Hostname</th><th>HTTP Detected</th><th>HTTPS Detected</th></tr></thead>');
|
||||
var header = $(`<thead>
|
||||
<tr>
|
||||
<th>IP Address</th>
|
||||
<th>Ping</th>
|
||||
<th>Hostname</th>
|
||||
<th>HTTP Detected</th>
|
||||
<th>HTTPS Detected</th>
|
||||
<th>Port Scan</th>
|
||||
</tr>
|
||||
</thead>`);
|
||||
table.append(header);
|
||||
var body = $('<tbody></tbody>');
|
||||
var offlineHostCounter = 0;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var classname = "offlinehost";
|
||||
if (data[i].Ping>=0){
|
||||
let hostIsOnline = data[i].Ping >= 0;
|
||||
if (hostIsOnline){
|
||||
classname = "onlinehost";
|
||||
}else{
|
||||
offlineHostCounter++;
|
||||
@ -167,6 +176,7 @@
|
||||
row.append($('<td>' + data[i].Hostname + '</td>'));
|
||||
row.append($('<td>' + (data[i].HttpPortDetected ? '<i class="green check icon"></i>' : '') + '</td>'));
|
||||
row.append($('<td>' + (data[i].HttpsPortDetected ? '<i class="green check icon"></i>' : '') + '</td>'));
|
||||
row.append($(`<td>${hostIsOnline ? `<button class="ui small basic button" onclick='launchToolWithSize("portscan.html?ip=${data[i].IP}", 1000, 640);'>Scan</button>`:''}</td>`));
|
||||
body.append(row);
|
||||
}
|
||||
|
||||
@ -198,6 +208,21 @@
|
||||
function toggleOfflineHost(){
|
||||
$(".offlinehost").toggle();
|
||||
}
|
||||
|
||||
function launchToolWithSize(url, width, height){
|
||||
let windowName = Date.now();
|
||||
window.open(url,'w'+windowName,
|
||||
`toolbar=no,
|
||||
location=no,
|
||||
status=no,
|
||||
menubar=no,
|
||||
scrollbars=yes,
|
||||
resizable=yes,
|
||||
width=${width},
|
||||
height=${height}`);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
120
src/web/tools/portscan.html
Normal file
120
src/web/tools/portscan.html
Normal file
@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta name="theme-color" content="#4b75ff">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<title>Port Scanner | Zoraxy</title>
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<script src="../script/utils.js"></script>
|
||||
</head>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ui container">
|
||||
<br>
|
||||
<div class="ui segment">
|
||||
<p>Enter the IP address you want to scan for open ports. This tool only scans for open TCP ports.</p>
|
||||
<div class="ui fluid action input">
|
||||
<input id="scanningIP" type="text" placeholder="IP Address">
|
||||
<button class="ui basic blue button" onclick="startScan()">Start Scan</button>
|
||||
</div>
|
||||
<div class="ui yellow message">
|
||||
<h4 class="ui header">
|
||||
<i class="exclamation triangle icon"></i>
|
||||
<div class="content">
|
||||
Port Scan Warning
|
||||
<div class="sub header">Please ensure that you only scan IP addresses that you own or have explicit permission to scan. Unauthorized scanning may be considered a network attack and could result in legal consequences.</div>
|
||||
</div>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<table class="ui celled compact table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Port</th>
|
||||
<th>TCP Port Open</th>
|
||||
<th>Full Path</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="resultTable">
|
||||
<tr>
|
||||
<td colspan="3"><i class="ui green circle check icon"></i> Click the "Start Scan" to start port scan on given IP address</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="ui right floated basic button" onclick="exitTool();">Exit</button>
|
||||
<br><br>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
|
||||
<script>
|
||||
|
||||
//If the URL has a query parameter, fill the input box with that value
|
||||
$(document).ready(function(){
|
||||
let urlParams = new URLSearchParams(window.location.search);
|
||||
let ipToScan = urlParams.get("ip");
|
||||
if (ipToScan != null){
|
||||
$("#scanningIP").val(ipToScan);
|
||||
startScan();
|
||||
}
|
||||
});
|
||||
|
||||
function startScan(button=undefined){
|
||||
let ipToScan = $("#scanningIP").val();
|
||||
ipToScan = ipToScan.trim();
|
||||
let table = $("#resultTable");
|
||||
table.empty();
|
||||
table.append($("<tr><td colspan='3'><i class='ui loading spinner icon'></i> Scanning</td></tr>"));
|
||||
|
||||
if (button != undefined){
|
||||
button.addClass("loading");
|
||||
}
|
||||
$.get("/api/tools/portscan?ip=" + ipToScan, function(data){
|
||||
if (button != undefined){
|
||||
button.removeClass("loading");
|
||||
}
|
||||
|
||||
if (data.error != undefined){
|
||||
alert(data.error);
|
||||
return;
|
||||
}else{
|
||||
table.empty();
|
||||
|
||||
//Entries are in the form of {Port: 80, IsTCP: true, IsUDP: false}
|
||||
//if both TCP and UDP are open, there will be two entries
|
||||
for (let i = 0; i < data.length; i++){
|
||||
let row = $("<tr></tr>");
|
||||
row.append($("<td></td>").text(data[i].Port));
|
||||
row.append($("<td><i class='ui green check icon'></i></td>"));
|
||||
row.append($("<td></td>").html(`<a href="//${ipToScan + ":" + data[i].Port}" target="_blank">${ipToScan + ":" + data[i].Port}</a>`));
|
||||
table.append(row);
|
||||
}
|
||||
|
||||
if (data.length == 0){
|
||||
table.append($("<tr><td colspan='3'><i class='ui green circle check icon'></i> No open ports found on given IP address</td></tr>"));
|
||||
}
|
||||
}
|
||||
console.log(data);
|
||||
});
|
||||
}
|
||||
|
||||
function exitTool(){
|
||||
//Close the current window
|
||||
window.open('', '_self', '');
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -26,7 +26,6 @@ import (
|
||||
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy"
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
|
||||
"imuslab.com/zoraxy/mod/ipscan"
|
||||
"imuslab.com/zoraxy/mod/mdns"
|
||||
"imuslab.com/zoraxy/mod/uptime"
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
@ -267,44 +266,6 @@ func HandleMdnsScanning(w http.ResponseWriter, r *http.Request) {
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
}
|
||||
|
||||
// handle ip scanning
|
||||
func HandleIpScan(w http.ResponseWriter, r *http.Request) {
|
||||
cidr, err := utils.PostPara(r, "cidr")
|
||||
if err != nil {
|
||||
//Ip range mode
|
||||
start, err := utils.PostPara(r, "start")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "missing start ip")
|
||||
return
|
||||
}
|
||||
|
||||
end, err := utils.PostPara(r, "end")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "missing end ip")
|
||||
return
|
||||
}
|
||||
|
||||
discoveredHosts, err := ipscan.ScanIpRange(start, end)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
js, _ := json.Marshal(discoveredHosts)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else {
|
||||
//CIDR mode
|
||||
discoveredHosts, err := ipscan.ScanCIDRRange(cidr)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
js, _ := json.Marshal(discoveredHosts)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
WAKE ON LAN
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user