mirror of
https://github.com/ditatompel/xmr-remote-nodes.git
synced 2024-12-22 19:49:25 +00:00
feat: Added IPv6 nodes support (alpha) #84
This commit accept IPv6 nodes submission. When user submit new public node, the server will check IP addresses from given hostname. If host IP addresses doesn't have IPv4, it will be recorded as "IPv6 only" node. Probers that support IPv6 may add `IPV6_CAPABLE=true` to the `.env` file. Please note that this feature still experimental and may not being merged to the main branch.
This commit is contained in:
parent
187a7bc84a
commit
518d4b4335
8 changed files with 67 additions and 21 deletions
|
@ -8,6 +8,7 @@ SERVER_ENDPOINT="http://127.0.0.1:18901"
|
||||||
API_KEY=
|
API_KEY=
|
||||||
ACCEPT_TOR=false
|
ACCEPT_TOR=false
|
||||||
TOR_SOCKS="127.0.0.1:9050"
|
TOR_SOCKS="127.0.0.1:9050"
|
||||||
|
IPV6_CAPABLE=false
|
||||||
|
|
||||||
# Server Config
|
# Server Config
|
||||||
# #############
|
# #############
|
||||||
|
|
|
@ -36,20 +36,22 @@ func (err errProber) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type proberClient struct {
|
type proberClient struct {
|
||||||
endpoint string // server endpoint
|
endpoint string // server endpoint
|
||||||
apiKey string // prober api key
|
apiKey string // prober api key
|
||||||
acceptTor bool // accept tor
|
acceptTor bool // accept tor
|
||||||
torSOCKS string // IP:Port of tor socks
|
torSOCKS string // IP:Port of tor socks
|
||||||
message string // message to include when reporting back to server
|
acceptIPv6 bool // accept ipv6
|
||||||
|
message string // message to include when reporting back to server
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProber() *proberClient {
|
func newProber() *proberClient {
|
||||||
cfg := config.AppCfg()
|
cfg := config.AppCfg()
|
||||||
return &proberClient{
|
return &proberClient{
|
||||||
endpoint: cfg.ServerEndpoint,
|
endpoint: cfg.ServerEndpoint,
|
||||||
apiKey: cfg.APIKey,
|
apiKey: cfg.APIKey,
|
||||||
acceptTor: cfg.AcceptTor,
|
acceptTor: cfg.AcceptTor,
|
||||||
torSOCKS: cfg.TorSOCKS,
|
torSOCKS: cfg.TorSOCKS,
|
||||||
|
acceptIPv6: cfg.IPv6Capable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +87,10 @@ func (p *proberClient) SetAcceptTor(acceptTor bool) {
|
||||||
p.acceptTor = acceptTor
|
p.acceptTor = acceptTor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *proberClient) SetAcceptIPv6(acceptIPv6 bool) {
|
||||||
|
p.acceptIPv6 = acceptIPv6
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch a new job from the server, fetches node info, and sends it to the server
|
// Fetch a new job from the server, fetches node info, and sends it to the server
|
||||||
func (p *proberClient) Run() error {
|
func (p *proberClient) Run() error {
|
||||||
if err := p.validateConfig(); err != nil {
|
if err := p.validateConfig(); err != nil {
|
||||||
|
@ -121,20 +127,26 @@ func (p *proberClient) validateConfig() error {
|
||||||
|
|
||||||
// Get monero node info to fetch from the server
|
// Get monero node info to fetch from the server
|
||||||
func (p *proberClient) fetchJob() (monero.Node, error) {
|
func (p *proberClient) fetchJob() (monero.Node, error) {
|
||||||
queryParams := ""
|
acceptTor := 0
|
||||||
if p.acceptTor {
|
if p.acceptTor {
|
||||||
queryParams = "?accept_tor=1"
|
acceptTor = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptIPv6 := 0
|
||||||
|
if p.acceptIPv6 {
|
||||||
|
acceptIPv6 = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var node monero.Node
|
var node monero.Node
|
||||||
|
|
||||||
uri := fmt.Sprintf("%s/api/v1/job%s", p.endpoint, queryParams)
|
uri := fmt.Sprintf("%s/api/v1/job?accept_tor=%d&accept_ipv6=%d", p.endpoint, acceptTor, acceptIPv6)
|
||||||
slog.Info(fmt.Sprintf("[PROBE] Getting node from %s", uri))
|
slog.Info(fmt.Sprintf("[PROBE] Getting node from %s", uri))
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, uri, nil)
|
req, err := http.NewRequest(http.MethodGet, uri, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Add(monero.ProberAPIKey, p.apiKey)
|
req.Header.Add(monero.ProberAPIKey, p.apiKey)
|
||||||
req.Header.Set("User-Agent", RPCUserAgent)
|
req.Header.Set("User-Agent", RPCUserAgent)
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
<section id="form-add-monero-node">
|
<section id="form-add-monero-node">
|
||||||
<div class="section-container text-center">
|
<div class="section-container text-center">
|
||||||
<p>Enter your Monero node information below (IPv4 host only):</p>
|
<p>Enter your Monero node information below (IPv6 host check is experimental):</p>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
class="mx-auto w-full max-w-3xl py-2"
|
class="mx-auto w-full max-w-3xl py-2"
|
||||||
|
|
|
@ -24,6 +24,7 @@ type App struct {
|
||||||
APIKey string
|
APIKey string
|
||||||
AcceptTor bool
|
AcceptTor bool
|
||||||
TorSOCKS string
|
TorSOCKS string
|
||||||
|
IPv6Capable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -65,4 +66,5 @@ func LoadApp() {
|
||||||
app.APIKey = os.Getenv("API_KEY")
|
app.APIKey = os.Getenv("API_KEY")
|
||||||
app.AcceptTor, _ = strconv.ParseBool(os.Getenv("ACCEPT_TOR"))
|
app.AcceptTor, _ = strconv.ParseBool(os.Getenv("ACCEPT_TOR"))
|
||||||
app.TorSOCKS = os.Getenv("TOR_SOCKS")
|
app.TorSOCKS = os.Getenv("TOR_SOCKS")
|
||||||
|
app.IPv6Capable, _ = strconv.ParseBool(os.Getenv("IPV6_CAPABLE"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
type migrateFn func(*DB) error
|
type migrateFn func(*DB) error
|
||||||
|
|
||||||
var dbMigrate = [...]migrateFn{v1, v2}
|
var dbMigrate = [...]migrateFn{v1, v2, v3}
|
||||||
|
|
||||||
func MigrateDb(db *DB) error {
|
func MigrateDb(db *DB) error {
|
||||||
version := getSchemaVersion(db)
|
version := getSchemaVersion(db)
|
||||||
|
@ -256,3 +256,19 @@ func v2(db *DB) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func v3(db *DB) error {
|
||||||
|
slog.Debug("[DB] Migrating database schema version 3")
|
||||||
|
|
||||||
|
// table: tbl_node
|
||||||
|
slog.Debug("[DB] Adding ipv6_only column to tbl_node")
|
||||||
|
_, err := db.Exec(`
|
||||||
|
ALTER TABLE tbl_node
|
||||||
|
ADD ipv6_only TINYINT(1) UNSIGNED NOT NULL DEFAULT '0'
|
||||||
|
AFTER cors_capable;`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -171,9 +171,10 @@ func Countries(c *fiber.Ctx) error {
|
||||||
// This handler should protected by `CheckProber` middleware.
|
// This handler should protected by `CheckProber` middleware.
|
||||||
func GiveJob(c *fiber.Ctx) error {
|
func GiveJob(c *fiber.Ctx) error {
|
||||||
acceptTor := c.QueryInt("accept_tor", 0)
|
acceptTor := c.QueryInt("accept_tor", 0)
|
||||||
|
acceptIPv6 := c.QueryInt("accept_ipv6", 0)
|
||||||
|
|
||||||
moneroRepo := monero.New()
|
moneroRepo := monero.New()
|
||||||
node, err := moneroRepo.GiveJob(acceptTor)
|
node, err := moneroRepo.GiveJob(acceptTor, acceptIPv6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(fiber.Map{
|
return c.JSON(fiber.Map{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
|
|
|
@ -54,6 +54,7 @@ type Node struct {
|
||||||
FailedCount uint `json:"failed_count,omitempty" db:"failed_count"`
|
FailedCount uint `json:"failed_count,omitempty" db:"failed_count"`
|
||||||
LastCheckStatus types.JSONText `json:"last_check_statuses" db:"last_check_status"`
|
LastCheckStatus types.JSONText `json:"last_check_statuses" db:"last_check_status"`
|
||||||
CORSCapable bool `json:"cors" db:"cors_capable"`
|
CORSCapable bool `json:"cors" db:"cors_capable"`
|
||||||
|
IPv6Only bool `json:"ipv6_only" db:"ipv6_only"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get node from database by id
|
// Get node from database by id
|
||||||
|
@ -197,16 +198,22 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
||||||
}
|
}
|
||||||
ip := ""
|
ip := ""
|
||||||
|
|
||||||
|
ipv6_only := true
|
||||||
|
|
||||||
if !is_tor {
|
if !is_tor {
|
||||||
hostIps, err := net.LookupIP(hostname)
|
hostIps, err := net.LookupIP(hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hostIp := hostIps[0].To4()
|
for _, hostIp := range hostIps {
|
||||||
if hostIp == nil {
|
if hostIp.To4() != nil {
|
||||||
return errors.New("Host IP is not IPv4")
|
ipv6_only = false
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostIp := hostIps[0]
|
||||||
if hostIp.IsPrivate() {
|
if hostIp.IsPrivate() {
|
||||||
return errors.New("IP address is private")
|
return errors.New("IP address is private")
|
||||||
}
|
}
|
||||||
|
@ -248,7 +255,8 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
||||||
lon,
|
lon,
|
||||||
date_entered,
|
date_entered,
|
||||||
last_checked,
|
last_checked,
|
||||||
last_check_status
|
last_check_status,
|
||||||
|
ipv6_only
|
||||||
) VALUES (
|
) VALUES (
|
||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
|
@ -260,6 +268,7 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
|
?,
|
||||||
?
|
?
|
||||||
)`,
|
)`,
|
||||||
protocol,
|
protocol,
|
||||||
|
@ -272,7 +281,8 @@ func (r *moneroRepo) Add(protocol string, hostname string, port uint) error {
|
||||||
0,
|
0,
|
||||||
time.Now().Unix(),
|
time.Now().Unix(),
|
||||||
0,
|
0,
|
||||||
string(statusDb))
|
string(statusDb),
|
||||||
|
ipv6_only)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ func (r *moneroRepo) Logs(q QueryLogs) (FetchLogs, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GiveJob returns node that should be probed for the next time
|
// GiveJob returns node that should be probed for the next time
|
||||||
func (r *moneroRepo) GiveJob(acceptTor int) (Node, error) {
|
func (r *moneroRepo) GiveJob(acceptTor, acceptIPv6 int) (Node, error) {
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
wq := []string{}
|
wq := []string{}
|
||||||
where := ""
|
where := ""
|
||||||
|
@ -117,6 +117,10 @@ func (r *moneroRepo) GiveJob(acceptTor int) (Node, error) {
|
||||||
wq = append(wq, "is_tor = ?")
|
wq = append(wq, "is_tor = ?")
|
||||||
args = append(args, 0)
|
args = append(args, 0)
|
||||||
}
|
}
|
||||||
|
if acceptIPv6 != 1 {
|
||||||
|
wq = append(wq, "ipv6_only = ?")
|
||||||
|
args = append(args, 0)
|
||||||
|
}
|
||||||
|
|
||||||
if len(wq) > 0 {
|
if len(wq) > 0 {
|
||||||
where = "WHERE " + strings.Join(wq, " AND ")
|
where = "WHERE " + strings.Join(wq, " AND ")
|
||||||
|
|
Loading…
Reference in a new issue