Port scan

This commit is contained in:
aceberg 2024-08-23 19:10:19 +07:00
parent 409274759f
commit 54513cddd9
8 changed files with 151 additions and 14 deletions

View file

@ -33,7 +33,7 @@ type Host struct {
// GuiData - all data sent to html page
type GuiData struct {
Config Conf
Hosts []Host
Host Host
Themes []string
Version string
}

26
internal/portscan/scan.go Normal file
View file

@ -0,0 +1,26 @@
package portscan
import (
"fmt"
"net"
"time"
)
// IsOpen - check one tcp port
func IsOpen(host, port string) bool {
timeout := 3 * time.Second
target := fmt.Sprintf("%s:%s", host, port)
conn, err := net.DialTimeout("tcp", target, timeout)
if err != nil {
return false
}
if conn != nil {
conn.Close()
return true
}
return false
}

View file

@ -3,11 +3,11 @@ package web
import (
// "log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/aceberg/WatchYourLAN/internal/db"
"github.com/aceberg/WatchYourLAN/internal/portscan"
)
func apiAll(c *gin.Context) {
@ -25,21 +25,28 @@ func apiHistory(c *gin.Context) {
func apiHost(c *gin.Context) {
idStr := c.Param("id")
id, _ := strconv.Atoi(idStr)
host := getHostByID(id, allHosts) // functions.go
host := getHostByID(idStr, allHosts) // functions.go
c.IndentedJSON(http.StatusOK, host)
}
func apiPort(c *gin.Context) {
addr := c.Param("addr")
port := c.Param("port")
state := portscan.IsOpen(addr, port)
c.IndentedJSON(http.StatusOK, state)
}
func apiEdit(c *gin.Context) {
idStr := c.Param("id")
name := c.Param("name")
toggleKnown := c.Param("known")
id, _ := strconv.Atoi(idStr)
host := getHostByID(id, allHosts) // functions.go
host := getHostByID(idStr, allHosts) // functions.go
if host.Date != "" {
host.Name = name

View file

@ -1,10 +1,14 @@
package web
import (
"strconv"
"github.com/aceberg/WatchYourLAN/internal/models"
)
func getHostByID(id int, hosts []models.Host) (oneHost models.Host) {
func getHostByID(idStr string, hosts []models.Host) (oneHost models.Host) {
id, _ := strconv.Atoi(idStr)
for _, host := range hosts {
if host.ID == id {

View file

@ -1,7 +1,6 @@
package web
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
@ -14,9 +13,8 @@ func hostHandler(c *gin.Context) {
guiData.Config = appConfig
idStr := c.Param("id")
log.Println("ID =", idStr)
guiData.Version = idStr
guiData.Host = getHostByID(idStr, allHosts)
c.HTML(http.StatusOK, "header.html", guiData)
c.HTML(http.StatusOK, "host.html", guiData)

View file

@ -0,0 +1,46 @@
let stop = false;
function stopScan() {
stop = true;
}
async function scanAddr() {
const addr = document.getElementById("hostIP").value;
let begin = document.getElementById("begin").value;
let end = document.getElementById("end").value;
if (begin == "") {
begin = 1
}
if (end == "") {
end = 65535
}
let portOpen = false;
stop = false;
document.getElementById('stopBtn').style.visibility = "visible";
for (let i = begin ; i <= end; i++) {
if (stop) {
break;
}
let url = '/api/port/'+addr+'/'+i;
portOpen = await (await fetch(url)).json();
document.getElementById("curPort").innerHTML = "Scanning port "+i;
if (portOpen) {
let html = genHTML(addr, i);
document.getElementById('foundPorts').insertAdjacentHTML('beforeend', html);
}
}
document.getElementById('stopBtn').style.visibility = "hidden";
}
function genHTML(addr, port) {
html = `<a href="http://${addr}:${port}">${port}</a>&nbsp;&nbsp;&nbsp;`;
return html;
}

View file

@ -1,5 +1,6 @@
{{ define "host.html" }}
<script src="/fs/public/js/scan.js"></script>
<body>
<div class="container-lg">
<div class="row">
@ -8,7 +9,47 @@
<div class="card-header">Host</div>
<div class="card-body table-responsive">
<table class="table table-borderless">
<tr>
<td>ID</td>
<td>{{ .Host.ID }}</td>
</tr>
<tr>
<td>Name</td>
<td>{{ .Host.Name }}</td>
</tr>
<tr>
<td>Iface</td>
<td>{{ .Host.Iface }}</td>
</tr>
<tr>
<td>IP</td>
<td><a href="http://{{ .Host.IP }}">{{ .Host.IP }}</a></td>
</tr>
<tr>
<td>MAC</td>
<td>{{ .Host.Mac }}</td>
</tr>
<tr>
<td>Hardware</td>
<td>{{ .Host.Hw }}</td>
</tr>
<tr>
<td>Date</td>
<td>{{ .Host.Date }}</td>
</tr>
<tr>
<td>Known</td>
<td>{{ .Host.Known }}</td>
</tr>
<tr>
<td>Online</td>
<td>{{ if eq .Host.Now 0 }}
<i class="bi bi-circle-fill" style="color:var(--bs-gray-500);"></i>
{{ else }}
<i class="bi bi-check-circle-fill" style="color:var(--bs-success);"></i>
{{ end }}
</td>
</tr>
</table>
</div>
</div>
@ -18,6 +59,20 @@
<div class="card border-primary">
<div class="card-header">Port scan</div>
<div class="card-body">
<form class="input-group">
<input id="begin" type="text" class="form-control" placeholder="1">
<input id="end" type="text" class="form-control" placeholder="65535">
<!-- To get from JS -->
<input type="hidden" id="hostIP" value="{{ .Host.IP }}">
<button onclick="scanAddr()" type="button" class="btn btn-primary">Scan</button>
</form>
<div style="display: flex; justify-content: space-between; visibility: hidden;" id="stopBtn" class="mt-2">
<button onclick="stopScan()" type="button" class="btn btn-warning">Stop</button>
<div id="curPort"></div>
</div>
<div id="foundPorts" class="mt-2">
<!-- JS here -->
</div>
</div>
</div>
</div>

View file

@ -43,9 +43,10 @@ func Gui(dirPath, nodePath string) {
router.StaticFS("/fs/", http.FS(pubFS)) // public
router.GET("/api/all", apiAll) // api.go
router.GET("/api/history", apiHistory) // api.go
router.GET("/api/host", apiHost) // api.go
router.GET("/api/edit/:id/:name/*known", apiEdit) // api.go
router.GET("/api/history", apiHistory) // api.go
router.GET("/api/host", apiHost) // api.go
router.GET("/api/port/:addr/:port", apiPort) // api.go
router.GET("/", indexHandler) // index.go
router.GET("/history/", historyHandler) // index.go