From d7fa9afb4a6f71790a373f51830b3991d45d6c70 Mon Sep 17 00:00:00 2001 From: bergware Date: Tue, 18 Mar 2025 18:41:57 +0100 Subject: [PATCH 1/5] Diagnostics: remove wireless username/password from diagnostics --- emhttp/plugins/dynamix/scripts/diagnostics | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/emhttp/plugins/dynamix/scripts/diagnostics b/emhttp/plugins/dynamix/scripts/diagnostics index fd728b59f..c05823b17 100755 --- a/emhttp/plugins/dynamix/scripts/diagnostics +++ b/emhttp/plugins/dynamix/scripts/diagnostics @@ -92,6 +92,7 @@ function anonymize($text, $select) { if (!preg_match($regex, $row)) { $row = preg_replace("/^(\s*\[\S).*(\S\])( => Array)$/","$1..$2$3",$row); $row = preg_replace("/^(\s*\[(cachePool|name|nameOrig|comment|flashGUID|regGUID|regTo|readList|writeList|csrf_token|NGINX_DEFAULTURL|NGINX_CERTNAME|NGINX_LANFQDN|NGINX_WANFQDN|NGINX_WANIP)\] => \S).*(\S)$/","$1..$3",$row); + $row = preg_replace('/(\[(USERNAME|PASSWORD)\] =>).*/','$1 removed',$row); } } return implode("\n", $rows); @@ -483,6 +484,10 @@ if (!$all) { run("sed -ri 's/^((disk|flash)(Read|Write)List.*=\")[^\"]+/\\1.../' ".escapeshellarg("/$diag/config/*.cfg")." 2>/dev/null"); // anonymize IP addresses maskIP("/$diag/config/network.cfg"); + // anonymize wireless credentials + if (file_exists("/$diag/config/wireless.cfg")) { + run("sed -ri 's/^((USERNAME|PASSWORD)=\")[^\"]+/\\1.../' ".escapeshellarg("/$diag/config/wireless.cfg")." 2>/dev/null"); + } } // include listening interfaces run("$docroot/webGui/scripts/show_interfaces ip|tr ',' '\n' >".escapeshellarg("/$diag/config/listen.txt")); From 8fb1974de3e7af372d9f305ef2d2ffea16646395 Mon Sep 17 00:00:00 2001 From: bergware Date: Wed, 19 Mar 2025 13:07:22 +0100 Subject: [PATCH 2/5] Docker: allow independent IPv4 and IPv6 selection for configured networks --- .../DockerSettings.page | 84 +++++++++---------- etc/rc.d/rc.docker | 4 +- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerSettings.page b/emhttp/plugins/dynamix.docker.manager/DockerSettings.page index abc663b9e..188029ff1 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerSettings.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerSettings.page @@ -113,6 +113,7 @@ function base_max($route) { function base_net($route) { return substr(explode('/',$route)[0],0,-2); } + function hide_wlan($network) { return $network=='wlan0' && lan_port(DockerUtil::port(),true)==1; } @@ -315,7 +316,7 @@ $hide_wlan = hide_wlan($network); _(IPv4 custom network on interface)_ (_(optional)_): (_(optional)_): case ($mask < 32): $prefix = $net[0].'.'.$net[1].'.'.$net[2]; $box = 3 ;break; } ?> -: > +: > **_(Subnet)_:** **_(Gateway)_:** - > + > **_(DHCP pool)_:**. (_(optional)_): (_(optional)_): $net_user = $dhcp6 ? str_replace("$net:","",base_net($dhcp6)) : ''; $mask_user = $dhcp6 ? explode('/',$dhcp6)[1] : $mask; ?> -: > +: > **_(Subnet)_:** **_(Gateway)_:** @@ -525,7 +526,7 @@ $net = normalize($network); $docker_dhcp = "DOCKER_DHCP_$net"; $hide_wlan = hide_wlan($network); ?> - +
@@ -773,47 +774,31 @@ function prepareDocker(form) { }); return true; } -function changeEdit(id,ip) { + +function changeEdit(id, ip) { var checked = $('#'+id).prop('checked'); - var id1 = '#'+id.substr(0,id.length-4); - if (ip==4) { - var name = id.substr(0,id.length-5).replace('DHCP','AUTO'); - var id2 = '#'+name.replace('AUTO','DHCP6')+'_'; - } else { - var name = id.substr(0,id.length-5).replace('DHCP6','AUTO'); - var id2 = '#'+name.replace('AUTO','DHCP')+'_'; - } + var id1 = '#'+id.substr(0,id.length-4); + var dhcp = (ip == 4) ? 'DHCP' : 'DHCP6'; + var name = id.substr(0,id.length-5).replace(dhcp,'AUTO'); + var auto = $('input:hidden[name="'+name+'"]'); if (checked) { $(id1+'line').removeClass('disabled'); $(id1+'dhcp').prop('disabled',false); - $(id2+'line').removeClass('disabled'); - $(id2+'dhcp').prop('disabled',false); - $(id2+'edit').prop('checked',true); + auto.val(auto.val().replace('no','')+ip); } else { $(id1+'line').addClass('disabled','disabled'); $(id1+'dhcp').prop('disabled',true); - $(id2+'line').addClass('disabled','disabled'); - $(id2+'dhcp').prop('disabled',true); - $(id2+'edit').prop('checked',false); - } - $('input:hidden[name="'+name+'"]').val(checked?'':'no'); - if (ip==4) { - changeDHCP(id,4,$('#'+id.replace('edit','dhcp')).prop('checked')); - id = id.replace('DHCP','DHCP6'); - $('#'+id).prop('checked',checked); - changeDHCP(id,6,$('#'+id.replace('edit','dhcp')).prop('checked')); - } else { - changeDHCP(id,6,$('#'+id.replace('edit','dhcp')).prop('checked')); - id = id.replace('DHCP6','DHCP'); - $('#'+id).prop('checked',checked); - changeDHCP(id,4,$('#'+id.replace('edit','dhcp')).prop('checked')); + auto.val(auto.val().replace(ip,'')); + if (auto.val() == '') auto.val('no'); } + changeDHCP(id, ip, $('#'+id.replace('edit','dhcp')).prop('checked')); } -function changeDHCP(id,ip,sid) { - if (sid==null) sid = true; + +function changeDHCP(id, ip, sid) { + if (sid == null) sid = true; var checked = $('#'+id).prop('checked') && sid; id = '#'+id.substr(0,id.length-4); - if (ip==4) { + if (ip == 4) { for (var b=1; b<=3; b++) if ($(id+b).length>0) $(id+b).prop('disabled',!checked); $(id+'mask').prop('disabled',!checked); if (checked) { @@ -833,14 +818,16 @@ function changeDHCP(id,ip,sid) { } } } -function customDHCP(id,ip) { + +function customDHCP(id, ip) { var checked = $('#'+id).prop('checked'); id = '#'+id.substr(0,id.length-4); $(id+'pool').prop('disabled',!checked); $(id+'size').prop('disabled',!checked); if (ip==4) checked ? $(id+'hosts').show() : $(id+'hosts').hide(); } -function changeCustom(id,ip) { + +function changeCustom(id, ip) { var checked = $('#'+id).prop('checked'); var device = id.substr(0,id.length-5).split('_').splice(2,2).join('.').toLowerCase(); id = '#'+id.substr(0,id.length-4); @@ -858,7 +845,8 @@ function changeCustom(id,ip) { $(id+'line').addClass('disabled','disabled'); } } -function changeMask(id,val) { + +function changeMask(id, val) { var mask = Math.pow(2,32-val); id = '#'+id.substr(0,id.length-4); $(id+'size').html('('+mask+' hosts)'); @@ -876,14 +864,17 @@ function changeMask(id,val) { if ($(cell+' option:selected').val()%step!=0) $(cell+' option:selected').removeAttr('selected'); } } -function changeHosts(id,val) { + +function changeHosts(id, val) { var mask = Math.pow(2,32-val); id = '#'+id.substr(0,id.length-4); $(id+'hosts').html('('+mask+' hosts)'); } + function ip2int(ip) { return ip.split('.').reduce(function(ipInt,octet){return (ipInt<<8)+parseInt(octet,10)},0)>>>0; } + function checkDHCP() { var good = true; $('#settingsForm').find('input[name^="DOCKER_DHCP_"]').each(function(){ @@ -913,6 +904,7 @@ function checkDHCP() { }); return good; } + function checkIP() { var validIP4 = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/; var validIP6 = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i; @@ -943,6 +935,7 @@ function checkIP() { if (error) {swal({title:"_(Invalid IPv6 range)_",text:"_(Please enter a valid range)_",type:'error',html:true,confirmButtonText:"_(Ok)_"}); return false;} return true; } + function showLogOptions(log) { if (log == 'no') { $('#DOCKER_LOG_OPTIONS').hide('slow'); @@ -950,9 +943,11 @@ function showLogOptions(log) { $('#DOCKER_LOG_OPTIONS').show('slow'); } } -function prepareFS(form,cookie,value) { + +function prepareFS(form, cookie, value) { if ($(form).find('input[type="submit"]').val()=='Cancel') $.removeCookie(cookie); else $.cookie(cookie,value); } + function btrfsScrub(path) { $.post('/webGui/include/FileSystemStatus.php',{cmd:'scrub',path:path},function(data) { if (data.indexOf('running')>0) { @@ -964,6 +959,7 @@ function btrfsScrub(path) { } }); } + var originalPath = $("#DOCKER_IMAGE_FILE2").val(); function updateLocation(val) { var content1 = $("#DOCKER_IMAGE_FILE1"); @@ -1002,6 +998,7 @@ function updateLocation(val) { break; } } + function updateBackingFS(val) { var backingfs = ""; var warning = document.getElementById("WARNING_BACKINGFS"); @@ -1012,9 +1009,11 @@ function updateBackingFS(val) { warning.style.display = "none"; } } + function checkbox_state(value) { $.post('/plugins/dynamix.docker.manager/include/UpdateConfig.php',{action:'exist',name:value},function(state){state==0 ? $('.deleteLabel').fadeIn() : $('.deleteLabel').fadeOut();}); } + $(function() { if ($('#DOCKER_IMAGE_TYPE').val()=='folder') { @@ -1110,5 +1109,6 @@ $(function() { $.cookie('dockersettings_view_mode', $('.advancedview').is(':checked') ? 'advanced':'basic', {expires:3650}); }); showStatus('pid','dockerd'); -}); +} +); diff --git a/etc/rc.d/rc.docker b/etc/rc.d/rc.docker index c86d8c1a3..a107308ef 100755 --- a/etc/rc.d/rc.docker +++ b/etc/rc.d/rc.docker @@ -327,7 +327,7 @@ docker_network_start(){ fi # add auto defined networks SUBNET=; GATEWAY=; SERVER=; RANGE=; - IPV4=$(ip -4 -br addr show $NETWORK scope global | awk '{print $3;exit}') + [[ -z ${!AUTO} || ${!AUTO} =~ "4" ]] && IPV4=$(ip -4 -br addr show $NETWORK scope global | awk '{print $3;exit}') || IPV4= if [[ -n $IPV4 ]]; then SUBNET=$(ip -4 route show $IPV4 dev $NETWORK | awk '{print $1;exit}') SERVER=${IPV4%/*} @@ -337,7 +337,7 @@ docker_network_start(){ GATEWAY=$(ip -4 route show default dev $NETWORK | awk '{print $3;exit}') fi SUBNET6=; GATEWAY6=; SERVER6=; - IPV6=$(ip -6 -br addr show $NETWORK scope global -temporary -deprecated | awk '{print $3;exit}') + [[ -z ${!AUTO} || ${!AUTO} =~ "6" ]] && IPV6=$(ip -6 -br addr show $NETWORK scope global -temporary -deprecated | awk '{print $3;exit}') || IPV6= if [[ -n $IPV6 ]]; then # get IPV6 subnet, preset to /64 if single host address is given [[ ${IPV6#*/} == 128 ]] && SUBNET6=$(echo $IPV6 | sed -r 's/^([^:]+):([^:]+):([^:]+):([^:]+).*$/\1:\2:\3:\4::\/64/') || SUBNET6=$(ip -6 route show $IPV6 dev $NETWORK | awk '{print $1;exit}') From 9f14e81621f37c0ced565ed900a662f25eb7c46a Mon Sep 17 00:00:00 2001 From: bergware Date: Wed, 19 Mar 2025 13:09:17 +0100 Subject: [PATCH 3/5] Docker: allow independent IPv4 and IPv6 selection for configured networks --- emhttp/plugins/dynamix.docker.manager/DockerSettings.page | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerSettings.page b/emhttp/plugins/dynamix.docker.manager/DockerSettings.page index 188029ff1..3102585b3 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerSettings.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerSettings.page @@ -1109,6 +1109,5 @@ $(function() { $.cookie('dockersettings_view_mode', $('.advancedview').is(':checked') ? 'advanced':'basic', {expires:3650}); }); showStatus('pid','dockerd'); -} -); +}); From a127aca670d9a768f974d49d4696a12b00ff7093 Mon Sep 17 00:00:00 2001 From: bergware Date: Wed, 19 Mar 2025 20:44:42 +0100 Subject: [PATCH 4/5] wireless: set wifi regulatory region when joining AP --- etc/rc.d/rc.wireless | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/etc/rc.d/rc.wireless b/etc/rc.d/rc.wireless index cf0670eb3..59f8635b9 100755 --- a/etc/rc.d/rc.wireless +++ b/etc/rc.d/rc.wireless @@ -266,7 +266,13 @@ wifi_join(){ else echo 1 >$CONF6/$PORT/disable_ipv6 fi - if wifi_running; then REPLY="Joined"; else REPLY="Failed"; fi + if wifi_running; then + CC=($(iw reg get | grep -Po '^country \K..')) + [[ ${CC[0]} != ${CC[1]} ]] && iw reg set ${CC[1]} + REPLY="Joined" + else + REPLY="Failed" + fi log "$DAEMON... $REPLY." } From a600dbc678c78d9cb7b78b730dd3620f907dcd77 Mon Sep 17 00:00:00 2001 From: bergware Date: Wed, 19 Mar 2025 22:20:44 +0100 Subject: [PATCH 5/5] diagnostics: anonymize IPv6 addresses in lsof.txt --- emhttp/plugins/dynamix/scripts/diagnostics | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/emhttp/plugins/dynamix/scripts/diagnostics b/emhttp/plugins/dynamix/scripts/diagnostics index c05823b17..30aafb658 100755 --- a/emhttp/plugins/dynamix/scripts/diagnostics +++ b/emhttp/plugins/dynamix/scripts/diagnostics @@ -58,6 +58,7 @@ function write(...$messages){ } curl_close($com); } + function run($cmd, &$save=null, $timeout=30) { global $cli,$diag; // output command for display @@ -77,6 +78,7 @@ function newline($file) { function shareDisks($share) { return str_replace(',',', ',exec("shopt -s dotglob; getfattr --no-dereference --absolute-names --only-values -n system.LOCATIONS ".escapeshellarg("/mnt/user/$share")." 2>/dev/null") ?: ""); } + function anonymize($text, $select) { global $all,$var,$pools,$customShares; if ($all) return $text; @@ -133,6 +135,7 @@ function maskIP($file) { // Handle any remaining edge cases, e.g., addresses with subnet masks run("sed -ri 's/(([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})(\/[0-9]{1,3})([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\7/g' $file_escaped 2>/dev/null"); } + function download_url($url, $path="", $bg=false, $timeout=15) { $ch = curl_init(); curl_setopt_array($ch,[ @@ -150,6 +153,7 @@ function download_url($url, $path="", $bg=false, $timeout=15) { if ($path) file_put_contents($path,$out); return $out ?: false; } + function geturls_certdetails($file, $hostname, $ip="") { // called by the geturls() function // best to ensure the file exists before calling this function @@ -186,6 +190,7 @@ function geturls_certdetails($file, $hostname, $ip="") { } return [$cn, $cn_priv, $type]; } + function geturls_checkhost($host, $hostpriv, $expectedip, $dnsserver) { // called by the geturls() function // dns lookups will fail if there is no TLD or if it is ".local", so skip it @@ -200,6 +205,7 @@ function geturls_checkhost($host, $hostpriv, $expectedip, $dnsserver) { } return ''; } + function geturls() { global $var,$path; extract(@parse_ini_file("$path/network.ini",true)); @@ -365,6 +371,7 @@ if ( is_file("/usr/local/emhttp/plugins/fix.common.problems/scripts/scan.php") ) run("/usr/local/emhttp/plugins/fix.common.problems/scripts/scan.php diagnostics",$ignore,60); } } + // don't anonymize system share names $vardomain = (array)@parse_ini_file('/boot/config/domain.cfg'); $vardocker = (array)@parse_ini_file('/boot/config/docker.cfg'); @@ -433,6 +440,7 @@ if (file_exists("$path/diskload.ini")){ } } } + file_put_contents("/$diag/system/loads.txt",$cpuload.implode("\r\n",$loadTxt)); // individual commands execution (suppress errors) @@ -451,6 +459,9 @@ run("dmidecode -qt0 2>/dev/null|todos >>".escapeshellarg("/$diag/system/motherbo run("cat /proc/meminfo 2>/dev/null|todos >".escapeshellarg("/$diag/system/meminfo.txt")); run("dmidecode --type 17 2>/dev/null|todos >>".escapeshellarg("/$diag/system/meminfo.txt")); +// mask IP addresses in lsof.txt +maskIP("/$diag/system/lsof.txt"); + // create ethernet information information (suppress errors) foreach ($ports as $port) { run("ethtool ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));