DNS improvements: CloudFlare proxy toggle styling, auto AAAA records, proxy defaults
- Fixed CloudFlare proxy toggle button to display as oblong with round dot - Enable CloudFlare proxy by default for all domains/subdomains except mail domains - Automatically add AAAA (IPv6) DNS records when creating domains/subdomains - Added GetServerIPv6() function to retrieve server IPv6 address - Updated DNS template styling and Angular.js binding for toggle buttons
This commit is contained in:
parent
0a331ab00c
commit
b1adb8f52e
|
|
@ -472,41 +472,60 @@
|
|||
}
|
||||
}
|
||||
|
||||
.proxy-toggle {
|
||||
appearance: none;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
background: #e8e9ff;
|
||||
border-radius: 24px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
input.proxy-toggle[type="checkbox"] {
|
||||
-webkit-appearance: none !important;
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
width: 50px !important;
|
||||
height: 26px !important;
|
||||
min-width: 50px !important;
|
||||
min-height: 26px !important;
|
||||
max-width: 50px !important;
|
||||
max-height: 26px !important;
|
||||
background: #ccc !important;
|
||||
border-radius: 13px !important;
|
||||
position: relative !important;
|
||||
cursor: pointer !important;
|
||||
transition: background 0.3s ease !important;
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
display: inline-block !important;
|
||||
vertical-align: middle !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
.proxy-toggle:checked {
|
||||
background: #5b5fcf;
|
||||
input.proxy-toggle[type="checkbox"]:checked {
|
||||
background: #5b5fcf !important;
|
||||
}
|
||||
|
||||
.proxy-toggle::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--bg-primary, white);
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
input.proxy-toggle[type="checkbox"]::before {
|
||||
content: '' !important;
|
||||
position: absolute !important;
|
||||
width: 22px !important;
|
||||
height: 22px !important;
|
||||
border-radius: 50% !important;
|
||||
background: white !important;
|
||||
top: 2px !important;
|
||||
left: 2px !important;
|
||||
transition: left 0.3s ease, transform 0.3s ease !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.proxy-toggle:checked::after {
|
||||
left: 26px;
|
||||
input.proxy-toggle[type="checkbox"]:checked::before {
|
||||
left: 26px !important;
|
||||
}
|
||||
|
||||
.proxy-toggle:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
input.proxy-toggle[type="checkbox"]:disabled {
|
||||
opacity: 0.5 !important;
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
input.proxy-toggle[type="checkbox"]:focus {
|
||||
outline: 2px solid rgba(91, 95, 207, 0.3) !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -876,7 +895,7 @@
|
|||
<input class="proxy-toggle"
|
||||
ng-click="enableProxy(record.name, record.proxy)"
|
||||
ng-disabled="!record.proxiable"
|
||||
ng-checked="record.proxy"
|
||||
ng-checked="record.proxy"
|
||||
type="checkbox">
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
|
|
|
|||
|
|
@ -1048,6 +1048,38 @@ class ACLManager:
|
|||
ipData = f.read()
|
||||
return ipData.split('\n', 1)[0]
|
||||
|
||||
@staticmethod
|
||||
def GetServerIPv6():
|
||||
"""
|
||||
Get the server's primary IPv6 address (non-link-local, non-loopback)
|
||||
Returns None if no IPv6 address is found
|
||||
"""
|
||||
try:
|
||||
import subprocess
|
||||
# Get IPv6 addresses, exclude link-local (fe80::) and loopback (::1)
|
||||
result = subprocess.run(
|
||||
['ip', '-6', 'addr', 'show'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
lines = result.stdout.split('\n')
|
||||
for line in lines:
|
||||
if 'inet6' in line and '::1' not in line and 'fe80::' not in line:
|
||||
# Extract IPv6 address (format: inet6 2a02:c207:2139:8929::1/64)
|
||||
parts = line.strip().split()
|
||||
if len(parts) >= 2:
|
||||
ipv6 = parts[1].split('/')[0]
|
||||
# Validate it's a real IPv6 (not link-local)
|
||||
if not ipv6.startswith('fe80::'):
|
||||
return ipv6
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error getting IPv6 address: {str(e)}')
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def CheckForPremFeature(feature):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -220,6 +220,15 @@ class DNS:
|
|||
|
||||
DNS.createDNSRecord(zone, topLevelDomain, "A", ipAddress, 0, 3600)
|
||||
|
||||
# AAAA Record (IPv6) - Required for mail delivery to Google, Outlook, etc.
|
||||
try:
|
||||
from plogical.acl import ACLManager
|
||||
ipv6Address = ACLManager.GetServerIPv6()
|
||||
if ipv6Address:
|
||||
DNS.createDNSRecord(zone, topLevelDomain, "AAAA", ipv6Address, 0, 3600)
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error creating AAAA record for {topLevelDomain}: {str(e)}')
|
||||
|
||||
# CNAME Records.
|
||||
|
||||
cNameValue = "www." + topLevelDomain
|
||||
|
|
@ -282,6 +291,15 @@ class DNS:
|
|||
|
||||
DNS.createDNSRecord(zone, mxValue, "A", ipAddress, 0, 3600)
|
||||
|
||||
# AAAA Record for mail (IPv6) - Required for mail delivery
|
||||
try:
|
||||
from plogical.acl import ACLManager
|
||||
ipv6Address = ACLManager.GetServerIPv6()
|
||||
if ipv6Address:
|
||||
DNS.createDNSRecord(zone, mxValue, "AAAA", ipv6Address, 0, 3600)
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error creating AAAA record for mail {mxValue}: {str(e)}')
|
||||
|
||||
## TXT Records for mail
|
||||
|
||||
# record = Records(domainOwner=zone,
|
||||
|
|
@ -365,6 +383,15 @@ class DNS:
|
|||
|
||||
DNS.createDNSRecord(zone, topLevelDomain, "A", ipAddress, 0, 3600)
|
||||
|
||||
# AAAA Record (IPv6) - Required for mail delivery to Google, Outlook, etc.
|
||||
try:
|
||||
from plogical.acl import ACLManager
|
||||
ipv6Address = ACLManager.GetServerIPv6()
|
||||
if ipv6Address:
|
||||
DNS.createDNSRecord(zone, topLevelDomain, "AAAA", ipv6Address, 0, 3600)
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error creating AAAA record for {topLevelDomain}: {str(e)}')
|
||||
|
||||
# CNAME Records.
|
||||
|
||||
cNameValue = "www." + topLevelDomain
|
||||
|
|
@ -427,6 +454,15 @@ class DNS:
|
|||
|
||||
DNS.createDNSRecord(zone, mxValue, "A", ipAddress, 0, 3600)
|
||||
|
||||
# AAAA Record for mail (IPv6) - Required for mail delivery
|
||||
try:
|
||||
from plogical.acl import ACLManager
|
||||
ipv6Address = ACLManager.GetServerIPv6()
|
||||
if ipv6Address:
|
||||
DNS.createDNSRecord(zone, mxValue, "AAAA", ipv6Address, 0, 3600)
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error creating AAAA record for mail {mxValue}: {str(e)}')
|
||||
|
||||
## TXT Records for mail
|
||||
|
||||
# record = Records(domainOwner=zone,
|
||||
|
|
@ -478,10 +514,27 @@ class DNS:
|
|||
|
||||
DNS.createDNSRecord(zone, actualSubDomain, "A", ipAddress, 0, 3600)
|
||||
|
||||
# AAAA Record for subdomain (IPv6)
|
||||
try:
|
||||
from plogical.acl import ACLManager
|
||||
ipv6Address = ACLManager.GetServerIPv6()
|
||||
if ipv6Address:
|
||||
DNS.createDNSRecord(zone, actualSubDomain, "AAAA", ipv6Address, 0, 3600)
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error creating AAAA record for subdomain {actualSubDomain}: {str(e)}')
|
||||
|
||||
## Mail Record
|
||||
|
||||
if ('mail.%s' % (actualSubDomain)).find('mail.mail') == -1:
|
||||
DNS.createDNSRecord(zone, 'mail.' + actualSubDomain, "A", ipAddress, 0, 3600)
|
||||
# AAAA Record for mail subdomain (IPv6) - Required for mail delivery
|
||||
try:
|
||||
from plogical.acl import ACLManager
|
||||
ipv6Address = ACLManager.GetServerIPv6()
|
||||
if ipv6Address:
|
||||
DNS.createDNSRecord(zone, 'mail.' + actualSubDomain, "AAAA", ipv6Address, 0, 3600)
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error creating AAAA record for mail subdomain {actualSubDomain}: {str(e)}')
|
||||
|
||||
# CNAME Records.
|
||||
|
||||
|
|
@ -656,17 +709,31 @@ class DNS:
|
|||
return 0
|
||||
|
||||
@staticmethod
|
||||
def createDNSRecordCloudFlare(cf, zone, name, type, value, priority, ttl):
|
||||
def createDNSRecordCloudFlare(cf, zone, name, type, value, priority, ttl, proxied=None):
|
||||
try:
|
||||
|
||||
if value.find('DKIM') > -1:
|
||||
value = value.replace('\n\t', '')
|
||||
value = value.replace('"', '')
|
||||
|
||||
# Only A and CNAME records can be proxied in CloudFlare
|
||||
# Determine if proxy should be enabled (default: True for A/CNAME, except for mail domains)
|
||||
if proxied is None and type in ['A', 'CNAME']:
|
||||
# Check if this is a mail domain (starts with 'mail.' or contains 'mail.')
|
||||
is_mail_domain = name.lower().startswith('mail.') or '.mail.' in name.lower()
|
||||
proxied = not is_mail_domain
|
||||
elif type not in ['A', 'CNAME']:
|
||||
# AAAA, MX, TXT, etc. cannot be proxied
|
||||
proxied = False
|
||||
|
||||
if ttl > 0:
|
||||
dns_record = {'name': name, 'type': type, 'content': value, 'ttl': ttl, 'priority': priority}
|
||||
else:
|
||||
dns_record = {'name': name, 'type': type, 'content': value, 'priority': priority}
|
||||
|
||||
# Only add proxied parameter for A and CNAME records
|
||||
if type in ['A', 'CNAME']:
|
||||
dns_record['proxied'] = proxied
|
||||
|
||||
cf.zones.dns_records.post(zone, data=dns_record)
|
||||
except BaseException as msg:
|
||||
|
|
|
|||
Loading…
Reference in New Issue