mirror of
				https://github.com/taigrr/godns
				synced 2025-01-18 04:03:25 -08:00 
			
		
		
		
	support for getting an IP from an interface, and skip DNS record update if IP address is the same with last one
This commit is contained in:
		
							parent
							
								
									78f52ebe54
								
							
						
					
					
						commit
						851e2d7e46
					
				| @ -19,6 +19,7 @@ | |||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "ip_url": "http://members.3322.org/dyndns/getip", |   "ip_url": "http://members.3322.org/dyndns/getip", | ||||||
|  |   "ip_interface": "eth0", | ||||||
|   "socks5_proxy": "", |   "socks5_proxy": "", | ||||||
|   "notify": { |   "notify": { | ||||||
|     "enabled": false, |     "enabled": false, | ||||||
|  | |||||||
| @ -74,6 +74,7 @@ func (handler *CloudflareHandler) DomainLoop(domain *godns.Domain, panicChan cha | |||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
|  | 	var lastIP string | ||||||
| 	for { | 	for { | ||||||
| 		currentIP, err := godns.GetCurrentIP(handler.Configuration) | 		currentIP, err := godns.GetCurrentIP(handler.Configuration) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @ -81,7 +82,11 @@ func (handler *CloudflareHandler) DomainLoop(domain *godns.Domain, panicChan cha | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		log.Println("Current IP is:", currentIP) | 		log.Println("Current IP is:", currentIP) | ||||||
| 		// TODO: check against locally cached IP, if no change, skip update | 		//check against locally cached IP, if no change, skip update | ||||||
|  | 		if (currentIP == lastIP){ | ||||||
|  | 			log.Printf("IP is the same as cached one. Skip update.\n") | ||||||
|  | 		} else { | ||||||
|  | 			lastIP = currentIP | ||||||
| 
 | 
 | ||||||
| 			log.Println("Checking IP for domain", domain.DomainName) | 			log.Println("Checking IP for domain", domain.DomainName) | ||||||
| 			zoneID := handler.getZone(domain.DomainName) | 			zoneID := handler.getZone(domain.DomainName) | ||||||
| @ -104,7 +109,7 @@ func (handler *CloudflareHandler) DomainLoop(domain *godns.Domain, panicChan cha | |||||||
| 			} else { | 			} else { | ||||||
| 				log.Println("Failed to find zone for domain:", domain.DomainName) | 				log.Println("Failed to find zone for domain:", domain.DomainName) | ||||||
| 			} | 			} | ||||||
| 
 | 		} | ||||||
| 		// Interval is 5 minutes | 		// Interval is 5 minutes | ||||||
| 		log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | 		log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | ||||||
| 		time.Sleep(time.Minute * godns.INTERVAL) | 		time.Sleep(time.Minute * godns.INTERVAL) | ||||||
|  | |||||||
| @ -36,6 +36,7 @@ func (handler *DNSPodHandler) DomainLoop(domain *godns.Domain, panicChan chan<- | |||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
|  | 	var lastIP string | ||||||
| 	for { | 	for { | ||||||
| 		log.Printf("Checking IP for domain %s \r\n", domain.DomainName) | 		log.Printf("Checking IP for domain %s \r\n", domain.DomainName) | ||||||
| 		domainID := handler.GetDomain(domain.DomainName) | 		domainID := handler.GetDomain(domain.DomainName) | ||||||
| @ -52,6 +53,12 @@ func (handler *DNSPodHandler) DomainLoop(domain *godns.Domain, panicChan chan<- | |||||||
| 		} | 		} | ||||||
| 		log.Println("currentIP is:", currentIP) | 		log.Println("currentIP is:", currentIP) | ||||||
| 
 | 
 | ||||||
|  | 		//check against locally cached IP, if no change, skip update | ||||||
|  | 		if (currentIP == lastIP){ | ||||||
|  | 			log.Printf("IP is the same as cached one. Skip update.\n") | ||||||
|  | 		}else{ | ||||||
|  | 			lastIP = currentIP | ||||||
|  | 			 | ||||||
| 			for _, subDomain := range domain.SubDomains { | 			for _, subDomain := range domain.SubDomains { | ||||||
| 
 | 
 | ||||||
| 				subDomainID, ip := handler.GetSubDomain(domainID, subDomain) | 				subDomainID, ip := handler.GetSubDomain(domainID, subDomain) | ||||||
| @ -76,7 +83,7 @@ func (handler *DNSPodHandler) DomainLoop(domain *godns.Domain, panicChan chan<- | |||||||
| 					log.Printf("%s.%s Current IP is same as domain IP, no need to update...\n", subDomain, domain.DomainName) | 					log.Printf("%s.%s Current IP is same as domain IP, no need to update...\n", subDomain, domain.DomainName) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 		}  | ||||||
| 		// Interval is 5 minutes | 		// Interval is 5 minutes | ||||||
| 		log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | 		log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | ||||||
| 		time.Sleep(time.Minute * godns.INTERVAL) | 		time.Sleep(time.Minute * godns.INTERVAL) | ||||||
|  | |||||||
| @ -39,6 +39,7 @@ func (handler *HEHandler) DomainLoop(domain *godns.Domain, panicChan chan<- godn | |||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
|  | 	var lastIP string | ||||||
| 	for { | 	for { | ||||||
| 		currentIP, err := godns.GetCurrentIP(handler.Configuration) | 		currentIP, err := godns.GetCurrentIP(handler.Configuration) | ||||||
| 
 | 
 | ||||||
| @ -48,6 +49,12 @@ func (handler *HEHandler) DomainLoop(domain *godns.Domain, panicChan chan<- godn | |||||||
| 		} | 		} | ||||||
| 		log.Println("currentIP is:", currentIP) | 		log.Println("currentIP is:", currentIP) | ||||||
| 
 | 
 | ||||||
|  | 		//check against locally cached IP, if no change, skip update | ||||||
|  | 		if (currentIP == lastIP){ | ||||||
|  | 			log.Printf("IP is the same as cached one. Skip update.\n") | ||||||
|  | 		} else { | ||||||
|  | 			lastIP = currentIP | ||||||
|  | 			 | ||||||
| 			for _, subDomain := range domain.SubDomains { | 			for _, subDomain := range domain.SubDomains { | ||||||
| 				log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName) | 				log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName) | ||||||
| 				handler.UpdateIP(domain.DomainName, subDomain, currentIP) | 				handler.UpdateIP(domain.DomainName, subDomain, currentIP) | ||||||
| @ -58,11 +65,12 @@ func (handler *HEHandler) DomainLoop(domain *godns.Domain, panicChan chan<- godn | |||||||
| 					godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP) | 					godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 		} | ||||||
| 		// Interval is 5 minutes | 		// Interval is 5 minutes | ||||||
| 		log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | 		log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | ||||||
| 		time.Sleep(time.Minute * godns.INTERVAL) | 		time.Sleep(time.Minute * godns.INTERVAL) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UpdateIP update subdomain with current IP | // UpdateIP update subdomain with current IP | ||||||
|  | |||||||
| @ -33,6 +33,9 @@ type Settings struct { | |||||||
| 	LogPath     string   `json:"log_path"` | 	LogPath     string   `json:"log_path"` | ||||||
| 	Socks5Proxy string   `json:"socks5_proxy"` | 	Socks5Proxy string   `json:"socks5_proxy"` | ||||||
| 	Notify      Notify   `json:"notify"` | 	Notify      Notify   `json:"notify"` | ||||||
|  | 	IPInterface string   `json:"ip_interface"` | ||||||
|  | 	//the code is not ready to update AAAA record | ||||||
|  | 	//IPType      string   `json:"ip_type"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // LoadSettings -- Load settings from config file | // LoadSettings -- Load settings from config file | ||||||
|  | |||||||
							
								
								
									
										82
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								utils.go
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ import ( | |||||||
| 	"log" | 	"log" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |     "net" | ||||||
| 
 | 
 | ||||||
| 	"golang.org/x/net/proxy" | 	"golang.org/x/net/proxy" | ||||||
| 	"gopkg.in/gomail.v2" | 	"gopkg.in/gomail.v2" | ||||||
| @ -43,8 +44,87 @@ const ( | |||||||
| 	CLOUDFLARE = "Cloudflare" | 	CLOUDFLARE = "Cloudflare" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // GetCurrentIP gets public IP from internet | //GetIPFromInterface gets IP address from the specific interface | ||||||
|  | func GetIPFromInterface(configuration *Settings) (string,error) { | ||||||
|  |  	ifaces, err := net.InterfaceByName(configuration.IPInterface) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Println("can't get network device "+configuration.IPInterface+":", err) | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	addrs, err  :=ifaces.Addrs(); | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Println("can't get address from "+configuration.IPInterface+":", err) | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, addr := range addrs { | ||||||
|  | 		var ip net.IP | ||||||
|  | 		switch v := addr.(type) { | ||||||
|  | 		case *net.IPNet: | ||||||
|  | 			ip = v.IP | ||||||
|  | 		case *net.IPAddr: | ||||||
|  | 			ip = v.IP | ||||||
|  | 		} | ||||||
|  | 		if (ip == nil){ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!(ip.IsGlobalUnicast() &&!(ip.IsUnspecified()||ip.IsMulticast()||ip.IsLoopback()||ip.IsLinkLocalUnicast()||ip.IsLinkLocalMulticast()||ip.IsInterfaceLocalMulticast()))){ | ||||||
|  | 			continue; | ||||||
|  | 		}  | ||||||
|  | 
 | ||||||
|  | 		//the code is not ready for updating an AAAA record | ||||||
|  | 		/* | ||||||
|  | 		if (isIPv4(ip.String())){ | ||||||
|  | 			if (configuration.IPType=="IPv6"){ | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 		}else{ | ||||||
|  | 			if (configuration.IPType!="IPv6"){ | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 		} */ | ||||||
|  | 		if (!isIPv4(ip.String())){ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return ip.String(),nil | ||||||
|  | 		  | ||||||
|  | 	} | ||||||
|  | 	return "", errors.New("can't get a vaild address from "+configuration.IPInterface) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isIPv4(ip string) bool{ | ||||||
|  | 	return strings.Count(ip, ":") < 2 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //GetCurrentIP gets an IP from either internet or specific interface, depending on configuration | ||||||
| func GetCurrentIP(configuration *Settings) (string, error) { | func GetCurrentIP(configuration *Settings) (string, error) { | ||||||
|  | 	var err error | ||||||
|  | 
 | ||||||
|  | 	if (configuration.IPUrl != ""){  | ||||||
|  | 		ip, err := GetIPOnline(configuration) | ||||||
|  | 		if (err != nil){ | ||||||
|  | 			log.Println("get ip online failed. Fallback to get ip from interface if possible.") | ||||||
|  | 		}else{ | ||||||
|  | 			return ip,nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (configuration.IPInterface != ""){ | ||||||
|  | 		ip, err := GetIPFromInterface(configuration) | ||||||
|  | 		if (err != nil){  | ||||||
|  | 			log.Println("get ip from interface failed. There is no more ways to try.") | ||||||
|  | 		}else{ | ||||||
|  | 			return ip,nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return "", err | ||||||
|  | } | ||||||
|  | // GetIPOnline gets public IP from internet | ||||||
|  | func GetIPOnline(configuration *Settings) (string, error) { | ||||||
| 	client := &http.Client{} | 	client := &http.Client{} | ||||||
| 
 | 
 | ||||||
| 	if configuration.Socks5Proxy != "" { | 	if configuration.Socks5Proxy != "" { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user