編輯 /etc/apache2/conf-available/charset.conf 加入
AddDefaultCharset UTF-8
編輯 .htaccess
AddDefaultCharset UTF-8
AddType 'text/html; charset=UTF-8' .html .htm
AddType 'application/json; charset=UTF-8' .json
2026年9月14日 星期一
Apache2 設定編碼方式
2026年8月25日 星期二
Nginx Reverse Proxy 設定範例
server {
listen 80 ;
listen [::]:80 ;
server_name 192.168.26.162;
set $backend_librenms "http://192.168.255.1";
location / {
# 注意:目標網址結尾「不要」加斜線 /
# 這樣存取 /ipam/xxx 時,會自動轉發至 http://hostname2/ipam/xxx
proxy_pass $backend_librenms;
# 傳送原始請求標頭
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 處理後端發出的 301/302 重導向(將 hostname2 替換為 hostname1)
proxy_redirect $backend_librenms $http_host;
# 停用快取與調整超時限制(適合 phpIPAM / NetBox 等管理工具)
proxy_buffering off;
proxy_read_timeout 90;
}
set $backend_ipam "http://192.168.255.2";
location /ipam {
# 注意:目標網址結尾「不要」加斜線 /
# 這樣存取 /ipam/xxx 時,會自動轉發至 http://hostname2/ipam/xxx
proxy_pass $backend_ipam;
# 傳送原始請求標頭
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 處理後端發出的 301/302 重導向(將 hostname2 替換為 hostname1)
proxy_redirect $backend_ipam $http_host;
# 停用快取與調整超時限制(適合 phpIPAM / NetBox 等管理工具)
proxy_buffering off;
proxy_read_timeout 90;
}
}
2026年7月28日 星期二
IDs assigned but not accepted
#Nginx 設定
http {
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;
}
測試
openssl s_client -connect host:443 -reconnect -state
HSTS(Strict Transport Security)
#Nginx 設定
server {
listen 443 ssl http2;
server_name example.com;
# 啟用 HSTS(建議維持至少 1 年 = 31536000 秒)
# includeSubDomains: 套用至所有子網域
# preload: 允許加入瀏覽器預載清單
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
#Apache2 設定
<VirtualHost *:443>
ServerName example.com
# 啟用 HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</VirtualHost>
測試
chrome://net-internals/#hsts
curl -I https://127.0.0.1
Plaintext
HTTP/2 200
...
strict-transport-security: max-age=31536000; includeSubDomains; preload
...
Qualys SSL Labs(權威檢測)
網址:https://www.ssllabs.com/ssltest/
HSTS Preload 狀態檢查
網址:https://hstspreload.org/
2026年2月6日 星期五
2025年9月19日 星期五
Debian 13 安裝Apache2 modsecurity
安裝
apt install -y apache2 libapache2-mod-security2
a2enmod security2
設定 ModSecurity 設定檔 /etc/modsecurity/modsecurity.conf
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
將 SecRuleEngine 的 DetectionOnly 改成 On
編輯 /etc/apache2/sites-enabled/000-default.conf 加入
SecRuleEngine On
ModSecurity 的核心指令(如 SecRuleEngine)預設不允許在 .htaccess 內使用
相關檔案
/etc/apache2/mods-enabled/security2.conf
/etc/apache2/mods-enabled/security2.load
/var/cache/modsecurity
/etc/modsecurity/*.conf
/usr/share/modsecurity-crs/*.load
測試方式
curl -i "http://localhost/?id=1%27%20OR%201=1"
curl http://127.0.0.1/index.html?exec=/bin/bash
curl -k https://127.0.0.1/index.html?exec=/bin/bash
Debian 13 安裝 nginx php
apt install nginx php-fpm
編輯 /etc/nginx/sites-enabled/default
location ~ \.php$ {
include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
}
2025年9月2日 星期二
PHP FILETIME UNIX Time 轉換
UNIX時間採用世界標準時1970年1月1日00:00:00開始的秒數(不考慮閏秒)。
Windows API使用SYSTEMTIME表示年月日時分秒毫秒;
FILETIME表示自世界標準時1601年1月1日00:00:00開始的100奈秒為單位
<?php
function ftime2utime($filetime_value){
// 1. 轉換為秒 ( FILETIME單位是100奈秒 )
$filetime_seconds = $filetime_value / 10000000;
// 2. 減去UNIX紀元的偏移量 (1970年1月1日到1601年1月1日)
$unix_timestamp = $filetime_seconds - 11644473600;
// 3. 使用date()函數格式化時間戳
$formatted_time = date('Y-m-d H:i:s', $unix_timestamp);
echo "FILETIME : " . $filetime_value . "\n";
echo "UNIX TIME: " . $unix_timestamp . "\n";
echo "format : " . $formatted_time . "\n";
}
function utime2ftime($unixTimestamp){
// 计算自 1601 年以来的 100 纳秒间隔
// 11644473600 是 1601 年 1 月 1 日 UTC 到 1970 年 1 月 1 日 UTC 的秒数 [1]
// 10,000,000 将秒转换为 100 纳秒间隔 [1]
$filetime = ($unixTimestamp + 11644473600) * 10000000;
echo "Unix Timestamp: " . $unixTimestamp . "\n";
echo "FILETIME (Hex): " . sprintf('%x', $filetime) . "\n";
echo "FILETIME: ". $filetime . "\n";
}
$unixTimestamp = 1759420800;
utime2ftime($unixTimestamp);
echo "\n";
$filetime_value = 134038944000000000;
ftime2utime($filetime_value);
?>
2025年9月1日 星期一
PHP 查詢 Windows AD objectGUID objectSid (string fromat)
<?php
function objectSid($binary_sid) {
if(strlen(decbin(~0)) == 64) //64bit PHP
{
// Get revision, indentifier, authority
$parts = unpack('Crev/x/nidhigh/Nidlow', $binary_sid);
// Set revision, indentifier, authority
$sid = sprintf('S-%u-%d', $parts['rev'], ($parts['idhigh']<<32) + $parts['idlow']);
// Translate domain
$parts = unpack('x8/V*', $binary_sid);
// Append if parts exists
if ($parts) $sid .= '-';
// Join all
return $sid.= join('-', $parts);
}
//32bit PHP
$sid = 'S-';
$sidinhex = str_split(bin2hex($binary_sid), 2);
// Byte 0 = Revision Level
$sid = $sid.hexdec($sidinhex[0]).'-';
// Byte 1-7 = 48 Bit Authority
$sid = $sid.hexdec($sidinhex[6].$sidinhex[5].$sidinhex[4].$sidinhex[3].$sidinhex[2].$sidinhex[1]);
// Byte 8 count of sub authorities - Get number of sub-authorities
$subauths = hexdec($sidinhex[7]);
//Loop through Sub Authorities
for($i = 0; $i < $subauths; $i++) {
$start = 8 + (4 * $i);
// X amount of 32Bit (4 Byte) Sub Authorities
$sid = $sid.'-'.hexdec($sidinhex[$start+3].$sidinhex[$start+2].$sidinhex[$start+1].$sidinhex[$start]);
}
return $sid;
}
function objectGUID($binaryGuid) {
$hexGuid = bin2hex($binaryGuid);
// Reorder and format according to standard GUID representation
$hex1 = substr($hexGuid, 6, 2) . substr($hexGuid, 4, 2) . substr($hexGuid, 2, 2) . substr($hexGuid, 0, 2);
$hex2 = substr($hexGuid, 10, 2) . substr($hexGuid, 8, 2);
$hex3 = substr($hexGuid, 14, 2) . substr($hexGuid, 12, 2);
$hex4 = substr($hexGuid, 16, 4);
$hex5 = substr($hexGuid, 20, 12);
return sprintf('%s-%s-%s-%s-%s', $hex1, $hex2, $hex3, $hex4, $hex5);
}
$user = 'user1'; //設定欲認證的帳號名稱
$ldappass = 'p@ssw0rd'; //設定欲認證的帳號密碼
$domain = 'test.loc'; //設定網域名稱
putenv('LDAPTLS_REQCERT=allow');
$ldapconn = @ldap_connect("ldaps://" . $domain) or die("無法連接至 $domain");
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
if ($ldapconn) { // binding to ldap server
$ldapbind = @ldap_bind($ldapconn, $user . '@' . $domain, $ldappass);
if ($ldapbind) { // verify binding
$result = @ldap_search($ldapconn, sprintf("dc=%s", (str_replace(".", ",dc=", $domain))), "(sAMAccountName=$user)");
if($result==false) echo "認證失敗";
else {
$entries = ldap_get_entries($ldapconn, $result);
$results2 = ldap_search($ldapconn, sprintf("dc=%s", (str_replace(".", ",dc=", $domain))),"(&(objectclass=group)(objectsid=*))", array("cn", "objectguid"));
$entries2 = ldap_get_entries($ldapconn, $results2);
for ($i=1; $i<$entries2['count']; $i++)
echo $entries2[$i]['cn'][0] . "\n" . objectGUID($entries2[$i]['objectguid'][0]) . "\n" . objectSid($entries2[$i]['objectsid'][0]) . "\n\n";
}
} else echo "認證失敗...";
}
?>
2025年8月21日 星期四
PHP 時區設定
date.timezone = 'Asia/Taipei'
程式中設定
date_default_timezone_set( 'Asia/Taipei')
Debian NGINX 設定 SSH Over HTTPS
安裝
apt install -y nginx libnginx-mod-stream
建立 NGINX 憑證
mkdir -p /etc/nginx/ssl
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
編輯 /etc/nginx/nginx.conf 加入
stream {
server {
listen 443 ssl; # Or 80 for HTTP
proxy_pass ssh_backend;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
#加密方式
ssl_protocols TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
}
upstream ssh_backend {
server 127.0.0.1:22; # Or the actual SSH server IP and port
}
}
編輯 /etc/nginx/nginx.conf
設定 HTTP Options
server_tokens off;
編輯 /etc/ssh/sshd_config 加入
DebianBanner no
連線方式
ssh -o ProxyCommand="openssl s_client -servername localhost -connect <nginx server>:443 2>&1" root@l -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR
ssh -o ProxyCommand="openssl s_client -connect <nginx server>:443 2>&1" user@ -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR
Apache2 錯誤訊息 SSLEngine
錯誤訊息
Invalid command 'SSLEngine', perhaps misspelled or defined by a module not included in the server configuration
執行
a2enmod ssl
2025年8月5日 星期二
Apache2 設定 HTTP 嚴格傳輸安全 (HSTS)
a2enmod headers
編輯 /etc/apache2/apache2.conf 加入
Header always set Strict-Transport-Security "max-age=31536000;
2025年5月19日 星期一
Apache2 錯誤訊息 'Header'
Apache2 錯誤訊息
Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration
缺相關 Module
a2enmod headers
apache2ctl -M | grep headers_module
2025年4月1日 星期二
Debian 12 NoVNC
安裝
apt install -y novnc apache2 php
Apache Module 設定
a2enmod rewrite
a2enmod headers
Apache VirtualHost <Directory> or <Location>設定
Header set Cache-Control "no-cache"
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]
index.php 內容
<?php
$NOVNC = "/usr/share/novnc/vnc.html";
$NOVNC = "/usr/share/novnc/v.html";
$NOVNC_DIR = dirname($NOVNC);
if($_SERVER["SCRIPT_URL"]=="/xxx") {
if($_REQUEST['host']!='') exit();
header("Content-Type: text/html");
readfile($NOVNC);
exit();
}
//novnc file_exists
$_t = $NOVNC_DIR . $_SERVER["SCRIPT_URL"];
if(file_exists($_t)) {
switch(pathinfo($_t, PATHINFO_EXTENSION)){
case "":
case "htm":
case "html":
case "pl":
case "md": exit(); break;
case "css": $x = "text/css"; break;
case "js" : $x = "text/javascript"; break;
default: $x = (new finfo(FILEINFO_MIME_TYPE))->file($_t);
}
header("Content-Type: $x");
readfile($_t);
exit();
}
?>
隱藏 Clipboard Connection Controls
修改 /usr/share/novnc/vnc.html
<!-- Clipboard -->
<input type="hidden" alt="Clipboard" src="app/images/clipboard.svg"
id="noVNC_clipboard_button" class="noVNC_button"
<!-- Connection Controls -->
<input type="hidden" alt="Disconnect" src="app/images/disconnect.svg"
id="noVNC_disconnect_button" class="noVNC_button"
title="Disconnect">
2025年2月20日 星期四
Debian 12 安裝 Joomla 5
系統最低需求
PHP 8.1.0 (Modules: json, simplexml, dom, zlib, gd, mysqlnd or pdo_mysql or pdo_pgsql)
MySQL 8.0.13 / MariaDB 10.4.0 / PostgreSQL 12.0
Apache 2.4 / Nginx 1.21 / Microsoft IIS 10
安裝範例
apt update;apt upgrade -y;apt install -y busybox wget
apt install nginx / apt install -y apache2
apt install -y php php-common php-curl php-fpm php-imap php-cli php-xml php-zip php-mbstring php-gd php-mysql
apt install -y mariadb-server mariadb-client
systemctl start mariadb;systemctl enable mariadb
export h=/var/www/html/joomla
mkdir -p ${h}; cd ${h}
wget -q -O- https://downloads.joomla.org/zh/cms/joomla5/5-2-4/Joomla_5-2-4-Stable-Full_Package.zip?format=zip|busybox unzip -
chown -R www-data:www-data ${h}
cd -
mysql -u root
MariaDB [(none)]> CREATE DATABASE joomla_db;
MariaDB [(none)]> CREATE USER joomla_user@'localhost' IDENTIFIED BY 'joomla5_p@ssw0rd';
MariaDB [(none)]> GRANT ALL on joomla_db.* to joomla_user@localhost;
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> EXIT
2025年2月3日 星期一
Debian 12 安裝 nginx reverse stream proxy
安裝
apt install -y nginx libnginx-mod-stream
編輯 /etc/nginx/nginx.conf 加入
stream {
server {
listen 3389;
proxy_pass 10.10.10.10:3389;
}
}
stream {
server {
listen 443;
proxy_pass admin;
}
upstream admin {
server 10.10.10.10:443;
}
}
2025年1月17日 星期五
PHP proc_open 摘要
<?php
$cmd = "sqlite3 1.db ";
$interactive_cmd = "insert into a (a1,a2) values('中文','許');";
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr ?? instead of a file
);
$stdout = "";
$stderr = "";
$process = proc_open($cmd, $descriptorspec, $pipes, NULL);
if (is_resource($process)) {
fwrite($pipes[0], $interactive_cmd . PHP_EOL);
fclose($pipes[0]);
while($s= fgets($pipes[1], 1024)) $stdout .= $s; // read from the pipe
fclose($pipes[1]);
// stderr optional:
while($s= fgets($pipes[2], 1024)) $stderr .= $s;
fclose($pipes[2]);
}
echo "stdout: $stdout \nstderr: $stderr\n";
?>
2024年12月10日 星期二
PHP $_SERVER['HTTP_REFERER'] 摘要
說明:
$_SERVER[‘HTTP_REFERER’] 來源於瀏覽器,不是所有都會設置且部份支援手動修改。
以下狀況會無效:
直接輸入網址訪問該網頁。
Javascript 打開的網址、重定向(window.location)網址及 FLASH 中的鏈接。
PHP header 或 meta refresh重定向的網址。
瀏覽器未加設置或修改
一般生效狀況:
<a></a>超鏈結
POST
GET