forked from dotfur/whois
162 lines
5.3 KiB
Go
162 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
port = "43"
|
|
whoisversion = "v0.01"
|
|
dataDir = "./data" // Directory where domain files are stored
|
|
crlf = "\r\n"
|
|
)
|
|
|
|
// Function to get metadata for a domain
|
|
func getDomainMetadata(domain string) (string, string, string, string, error) {
|
|
metaFilePath := fmt.Sprintf("%s/%s.meta", dataDir, domain)
|
|
file, err := os.Open(metaFilePath)
|
|
if err != nil {
|
|
return "", "", "", "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
var registrar, registrationDate, expirationDate, status string
|
|
if scanner.Scan() {
|
|
registrar = scanner.Text()
|
|
}
|
|
if scanner.Scan() {
|
|
registrationDate = scanner.Text()
|
|
}
|
|
if scanner.Scan() {
|
|
expirationDate = scanner.Text()
|
|
}
|
|
if scanner.Scan() {
|
|
status = scanner.Text()
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return "", "", "", "", err
|
|
}
|
|
|
|
return registrar, registrationDate, expirationDate, status, nil
|
|
}
|
|
|
|
func handleConnection(conn net.Conn) {
|
|
defer conn.Close()
|
|
|
|
// Get the client's IP address
|
|
clientIP := conn.RemoteAddr().String()
|
|
|
|
// Read the domain name from the client
|
|
reader := bufio.NewReader(conn)
|
|
request, err := reader.ReadString('\n')
|
|
if err != nil {
|
|
log.Println("Error reading from connection:", err)
|
|
return
|
|
}
|
|
|
|
// Clean up the request
|
|
domain := strings.TrimSpace(request)
|
|
|
|
// Get the current timestamp
|
|
timestamp := time.Now().Format(time.RFC3339)
|
|
|
|
// Check if the domain file exists
|
|
filePath := fmt.Sprintf("%s/%s", dataDir, domain)
|
|
domainInfo, err := ioutil.ReadFile(filePath)
|
|
if err != nil {
|
|
// Domain file not found, so check if metadata file exists
|
|
metaFilePath := fmt.Sprintf("%s/%s.meta", dataDir, domain)
|
|
if _, err := os.Stat(metaFilePath); err == nil {
|
|
// Metadata file exists but domain file doesn't
|
|
registrar, registrationDate, expirationDate, status, err := getDomainMetadata(domain)
|
|
if err != nil {
|
|
log.Println("Error reading metadata file:", err)
|
|
conn.Write([]byte("Error reading domain metadata" + crlf))
|
|
return
|
|
}
|
|
response := fmt.Sprintf(" __ __ ____ \n ____/ /____ / /_ / __/__ __ _____\n / __ // __ \\ / __/ / /_ / / / // ___/\n/ /_/ // /_/ // /_ _ / __// /_/ // / | \n\\__,_/ \\____/ \\__/(_)/_/ \\__,_//_/ | dot.fur WHOIS Server\n _ __ __ __ ____ ____ _____ | whois.fur | whois.dotfur.net\n| | / // / / // __ \\ / _// ___/ | Version: %s\n| | /| / // /_/ // / / / / / \\__ \\ |\n| |/ |/ // __ // /_/ /_/ / ___/ / \n|__/|__//_/ /_/ \\____//___/ /____/ \n \n", whoisversion)
|
|
response += fmt.Sprintf(
|
|
"Domain: %s%sOrigin IP: %s%sTimestamp: %s%sRegistrar: %s%sRegistration Date: %s%sExpiration Date: %s%sStatus: %s%sNo WHOIS Info to show%s",
|
|
domain, crlf,
|
|
clientIP, crlf,
|
|
timestamp, crlf,
|
|
registrar, crlf,
|
|
registrationDate, crlf,
|
|
expirationDate, crlf,
|
|
status, crlf,
|
|
crlf)
|
|
response += fmt.Sprintf("\n.fur WHOIS Server | https://git.fur/caramel/whois | Version: %s", whoisversion)
|
|
response += crlf
|
|
|
|
conn.Write([]byte(response))
|
|
} else {
|
|
// Both domain file and metadata file not found
|
|
log.Println("Domain and metadata file not found")
|
|
conn.Write([]byte("Domain not found" + crlf))
|
|
}
|
|
return
|
|
}
|
|
|
|
// Domain file found, get metadata for the domain
|
|
registrar, registrationDate, expirationDate, status, err := getDomainMetadata(domain)
|
|
if err != nil {
|
|
log.Println("Error reading metadata file:", err)
|
|
conn.Write([]byte("Error reading domain metadata" + crlf))
|
|
return
|
|
}
|
|
|
|
// Format the response with additional fields, origin IP, and timestamp
|
|
response := fmt.Sprintf(" __ __ ____ \n ____/ /____ / /_ / __/__ __ _____\n / __ // __ \\ / __/ / /_ / / / // ___/\n/ /_/ // /_/ // /_ _ / __// /_/ // / | \n\\__,_/ \\____/ \\__/(_)/_/ \\__,_//_/ | dot.fur WHOIS Server\n _ __ __ __ ____ ____ _____ | whois.fur | whois.dotfur.net\n| | / // / / // __ \\ / _// ___/ | Version: %s\n| | /| / // /_/ // / / / / / \\__ \\ |\n| |/ |/ // __ // /_/ /_/ / ___/ / \n|__/|__//_/ /_/ \\____//___/ /____/ \n \n", whoisversion)
|
|
response += fmt.Sprintf(
|
|
"Domain: %s%sOrigin IP: %s%sTimestamp: %s%sRegistrar: %s%sRegistration Date: %s%sExpiration Date: %s%sStatus: %s%s%s",
|
|
domain, crlf,
|
|
clientIP, crlf,
|
|
timestamp, crlf,
|
|
registrar, crlf,
|
|
registrationDate, crlf,
|
|
expirationDate, crlf,
|
|
status, crlf,
|
|
string(domainInfo))
|
|
|
|
// Add a final CRLF to signify the end of the response
|
|
response += fmt.Sprintf("\n.fur WHOIS Server | https://git.fur/caramel/whois | Version: %s", whoisversion)
|
|
response += crlf
|
|
|
|
// Send the response back to the client
|
|
conn.Write([]byte(response))
|
|
|
|
log.Printf("Served domain: %s to %s at %s\n", domain, clientIP, timestamp)
|
|
}
|
|
|
|
func main() {
|
|
// Start the TCP server
|
|
listener, err := net.Listen("tcp", ":"+port)
|
|
if err != nil {
|
|
log.Fatalf("Error starting server: %s", err)
|
|
}
|
|
defer listener.Close()
|
|
|
|
log.Printf("Whois server running on port %s\n", port)
|
|
|
|
for {
|
|
// Accept incoming connections
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
log.Println("Error accepting connection:", err)
|
|
continue
|
|
}
|
|
|
|
// Handle the connection in a new goroutine
|
|
go handleConnection(conn)
|
|
}
|
|
}
|