顯示具有 Web 相關技術 標籤的文章。 顯示所有文章
顯示具有 Web 相關技術 標籤的文章。 顯示所有文章

2026年9月14日 星期一

Apache2 設定編碼方式

編輯  /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年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 時區設定

編輯 /etc/php/8.2/cli/php.ini   /etc/php/8.2/apache2/php.ini 加入
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 安全設定相關項目

隱藏 Apache 版本、作業系統、PHP 版本
設定 HTTP 嚴格傳輸安全 (HSTS)
自定錯誤訊息
加密設定
HTTP 自動導向 HTTPS

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