plugins icon indicating copy to clipboard operation
plugins copied to clipboard

os-ddclient: FEATURE REQUEST. Add interface restart if the ISP gave a private address

Open Slenkis opened this issue 6 months ago • 14 comments

https://github.com/opnsense/plugins/tree/master/dns/ddclient

  • [ x ] I have read the contributing guide lines at https://github.com/opnsense/plugins/blob/master/CONTRIBUTING.md
  • [ x ] I have searched the existing issues, open and closed, and I'm convinced that mine is new.
  • [ x ] When the request is meant for an existing plugin, I've added its name to the title.

my internet provider has a 50% chance of issuing a dynamic global v4 address.

is it possible to add a trigger to this plugin that would reboot the interface selected for monitoring (if the provider issued a private address) in order to select a global address?

I think this will be popular, because some providers also have dynamic pools of public and private addresses and issue them randomly.

Slenkis avatar May 06 '25 09:05 Slenkis

my internet provider has a 50% chance of issuing a dynamic global v4 address.

I'm not sure you came to the right place. Assuming this is DHCP you are looking at a setup issue, complicated by your ISP. And it could also be your modem.

fichtner avatar May 06 '25 09:05 fichtner

my internet provider has a 50% chance of issuing a dynamic global v4 address.

I'm not sure you came to the right place. Assuming this is DHCP you are looking at a setup issue, complicated by your ISP. And it could also be your modem.

connection type in my case specifically - PPPoE. I have this plugin configured and in the log I get a warning when the address on the interface is private. therefore this can be processed somehow to cause a restart of the interface.

Slenkis avatar May 06 '25 09:05 Slenkis

The warning is purely for diagnostics purposes. Your ISP shouldn't do this.

What kind of private range are we talking about anyway?

fichtner avatar May 06 '25 09:05 fichtner

The warning is purely for diagnostics purposes. Your ISP shouldn't do this.

What kind of private range are we talking about anyway?

Warning ddclient Account 0b2ac34e-fa7d-4af7-9294-c256a924a4e9 [cloudflare - cloudflare] no global IP address detected, check config if warning persists

Probably cloudflare itself sends such a response and ddclient only outputs it to the log. The range of private addresses is, for example, 192.168.0.0/16, 10.0.0.0/8, 100.64.0.0/10 (CGNAT)

Slenkis avatar May 06 '25 10:05 Slenkis

The warning is purely for diagnostics purposes. Your ISP shouldn't do this.

What kind of private range are we talking about anyway?

For example, I generated a piece of code that checks the address on the interface and, if necessary, reboots the interface.

#!/usr/bin/env python3

import subprocess
import re
import time
import syslog

INTERFACE = "pppoe0"
PRIVATE_IP_PATTERNS = [
    r"^10\.",
    r"^192\.168\.",
    r"^172\.(1[6-9]|2[0-9]|3[0-1])\.",
    r"^100\.(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])\."
]

def log(message):
    syslog.openlog(ident="pppoe-check", logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
    syslog.syslog(syslog.LOG_INFO, message)
    syslog.closelog()

def get_ip_address():
    try:
        output = subprocess.check_output(["ifconfig", INTERFACE], text=True)
        match = re.search(r'inet (\d+\.\d+\.\d+\.\d+)', output)
        if match:
            return match.group(1)
    except subprocess.CalledProcessError:
        log(f"Error: Could not get IP address for interface {INTERFACE}")
    return None

def is_private_ip(ip):
    for pattern in PRIVATE_IP_PATTERNS:
        if re.match(pattern, ip):
            return True
    return False

def restart_interface():
    subprocess.call(["ifconfig", INTERFACE, "down"])
    time.sleep(3)
    subprocess.call(["ifconfig", INTERFACE, "up"])

def main():
    ip = get_ip_address()
    if not ip:
        log("No IP address found.")
        return

    if is_private_ip(ip):
        log(f"Private IP {ip} detected on {INTERFACE}. Restarting interface.")
        restart_interface()
    else:
        log(f"Public IP {ip} detected on {INTERFACE}. No action needed.")

if __name__ == "__main__":
    main()

Slenkis avatar May 06 '25 10:05 Slenkis

Different private ranges? Could it be your ISP is so dense and allow clients to run DHCP servers on their WAN switches?

In theory dyndns should be restarted but jolting the interface with up/down until it behaves is probably not making ddclient behave better.

fichtner avatar May 06 '25 10:05 fichtner

I see you are talking about PPPoE which has nothing to do with DHCP so this is even more baffling. Sorry, I don't think I can help here.

fichtner avatar May 06 '25 10:05 fichtner

Different private ranges? Could it be your ISP is so dense and allow clients to run DHCP servers on their WAN switches?

In theory dyndns should be restarted but jolting the interface with up/down until it behaves is probably not making ddclient behave better.

No. My specific provider gives either a public one or a private one that starts with 100.100... if I restart pppoe, there's a 50% chance I can get a public address.

If the ideology of ddclient does not allow to implement this functionality, then I would be glad to make a fork based on this plugin. Tell me what files can be taken as a basis, because monitoring of van addresses is already implemented in ddclient

Slenkis avatar May 06 '25 13:05 Slenkis

If the ideology of ddclient does not allow to implement this functionality

I think you are confusing responsibilities: dyndns only makes sense with public IPs because you cannot reach private IP addresses from the Internet.

Now, providing a private address IS the actual issue and ddclient has a grace period and worst case your DynDNS provider has a policy of how often you can attempt to update your domain. There are probably ways to force the update, but then we would have to ask the right questions...

fichtner avatar May 06 '25 14:05 fichtner

Dyndns is for setting DNS Records to dynamic DNS zones.

It is the wrong tool for what you want.

From what I understand, you want to play IP address lottery with your provider. If the DHCP client on WAN receives an RFC1918 address, you want to reconnect PPPoE to redraw a new lottery ticket for a public one.

This must be one of the weirdest ISP issues I have ever heard and I would definitely choose a different provider.

Monviech avatar May 06 '25 14:05 Monviech

I understand that ddclient works only with dns records and my request is not its area of responsibility. My case is to check the issued address and if it is private - restart pppoe interface. Probably, it is possible to partially borrow logic from ddclient so that I could create a plugin that would monitor the address type on the interface. Probably, it should be done using the system tool "monit". I dont know...

Slenkis avatar May 06 '25 15:05 Slenkis

But it seems to me that it is much more logical to add functionality via a pull request than to multiply identical plugins.

Slenkis avatar May 07 '25 06:05 Slenkis

Using monit or a cron job with a custom script might be the best solution for you. Since its a very individual solution, I'm not sure a PR is worth the effort.

Monviech avatar May 07 '25 07:05 Monviech

Using monit or a cron job with a custom script might be the best solution for you. Since its a very individual solution, I'm not sure a PR is worth the effort.

Monit turned out to be quite extensive and difficult. that's why I'm more and more inclined to add a separate IP verification script to the ddclient.

For example, as in the attached photo. Unfortunately I have no experience in developing plugins for opnsense. I would be glad if you could describe in a few words what I should edit or create to achieve the result as on the photo.

That is, in fact, to create my own handler, which will check whether the address of the interface (I will copy the logic of obtaining the address from “Interface [IPv4]”) belongs to the range of private addresses. If so, I will restart the selected "Interface to monitor".


UPDATE 1:

I found the processing logic. I'll try to add my own handler.

https://github.com/opnsense/plugins/blob/b8af35970ea0963cb4cdf405334f5294311e2382/dns/ddclient/src/opnsense/scripts/ddclient/lib/address.py#L113


My solution:

if address.is_global:
  return str(address)
else:
  os.system(f"/usr/local/sbin/configctl interface linkup start {interface}")

Photo>

Image

Slenkis avatar May 07 '25 21:05 Slenkis

This issue has been automatically timed-out (after 180 days of inactivity).

For more information about the policies for this repository, please read https://github.com/opnsense/plugins/blob/master/CONTRIBUTING.md for further details.

If someone wants to step up and work on this issue, just let us know, so we can reopen the issue and assign an owner to it.

OPNsense-bot avatar Nov 02 '25 09:11 OPNsense-bot