-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
95 lines (78 loc) · 2.08 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package main
import (
"fmt"
"net"
"net/http"
"strconv"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
type Record struct {
Address string `json:"address" binding:"required"`
Port string `json:"port" binding:"required"`
}
func main() {
r := gin.Default()
r.SetTrustedProxies(nil)
// middleware
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.Use(cors.Default())
r.POST("/check", checkPortHandler)
r.GET("/ipv4", getIpv4Handler)
r.Run()
}
// checkPortHandler check if port is open or closed on given IP address
func checkPortHandler(c *gin.Context) {
// validate payload format
record := &Record{}
if err := c.BindJSON(record); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "invalid payload"})
return
}
// validate address input
if !isIp(record.Address) {
c.JSON(http.StatusNotAcceptable, gin.H{"message": fmt.Sprintf("%v is not a valid IP address", record.Address)})
return
}
// validate port input
if !isPort(record.Port) {
c.JSON(http.StatusNotAcceptable, gin.H{"message": fmt.Sprintf("%v is not a valid port", record.Port)})
return
}
err := tcpCheck(record.Address, record.Port)
if err != nil {
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("port %v closed on %v", record.Port, record.Address)})
} else {
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("port %v open on %v", record.Port, record.Address)})
}
}
// getIpv4Handler returns the public IPv4 address of the request
func getIpv4Handler(c *gin.Context) {
c.String(http.StatusOK, "%v", c.ClientIP())
}
// tcpCheck run tcp port check and return if given port is open or closed
func tcpCheck(addr, port string) error {
timeout := time.Second
_, err := net.DialTimeout("tcp4", net.JoinHostPort(addr, port), timeout)
if err != nil {
return err
}
return nil
}
// isIp validate given IP address
func isIp(addr string) bool {
return net.ParseIP(addr) != nil
}
// isPort validate given port number
func isPort(port string) bool {
p, err := strconv.ParseInt(port, 10, 0)
if err != nil {
return false
}
if p <= 0 || p >= 65535 {
return false
}
return true
}