Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
:如何對我存放在 /var/www/html/
目錄中的所有文件設置只讀權限?
你可以使用 chmod
命令對 Linux/Unix/macOS/OS X/*BSD 操作系統上的所有文件來設置只讀權限。這篇文章介紹如何在 Linux/Unix 的 web 服務器(如 Nginx、 Lighttpd、 Apache 等)上來設置只讀文件權限。
如何設置文件為只讀模式
語法為:
### 僅針對文件 ###
chmod 0444 /var/www/html/*
chmod 0444 /var/www/html/*.php
如何設置目錄為只讀模式
語法為:
### 僅針對目錄 ###
chmod 0444 /var/www/html/
chmod 0444 /path/to/your/dir/
# ***************************************************************************
# 假如 web 服務器的用戶/用戶組是 www-data,文件擁有者是 ftp-data 用戶/用戶組
# ***************************************************************************
# 設置目錄所有文件為只讀
chmod -R 0444 /var/www/html/
# 設置文件/目錄擁有者為 ftp-data
chown -R ftp-data:ftp-data /var/www/html/
# 所有目錄和子目錄的權限為 0445 (這樣 web 服務器的用戶或用戶組就可以讀取我們的文件)
find /var/www/html/ -type d -print0 | xargs -0 -I {} chmod 0445 "{}"
找到所有 /var/www/html
下的所有文件(包括子目錄),鍵入:
### 僅對文件有效 ###
find /var/www/html -type f -iname "*" -print0 | xargs -I {} -0 chmod 0444 {}
然而,你需要在 /var/www/html
目錄及其子目錄上設置只讀和執行權限,如此才能讓 web 服務器能夠訪問根目錄,鍵入:
### 僅對目錄有效 ###
find /var/www/html -type d -iname "*" -print0 | xargs -I {} -0 chmod 0544 {}
警惕寫權限
請注意在 /var/www/html/
目錄上的寫權限會允許任何人刪除文件或添加新文件。也就是說,你可能需要設置一個只讀權限給 /var/www/html/
目錄本身。
### web根目錄只讀 ###
chmod 0555 /var/www/html
在某些情況下,根據你的設置要求,你可以改變文件的屬主和屬組來設置嚴格的權限。
### 如果 /var/www/html 目錄的擁有人是普通用戶,你可以設置擁有人為:root:root 或 httpd:httpd (推薦) ###
chown -R root:root /var/www/html/
### 確保 apache 擁有 /var/www/html/ ###
chown -R apache:apache /var/www/html/
關于 NFS 導出目錄
你可以在 /etc/exports
文件中指定哪個目錄應該擁有只讀或者讀寫權限 [1]。這個文件定義各種各樣的共享在 NFS 服務器和他們的權限。如:
# 對任何人只讀權限
/var/www/html *(ro,sync)
# 對192.168.1.10(upload.example.com)客戶端讀寫權限訪問
/var/www/html 192.168.1.10(rw,sync)
關于用于 MS-Windows客戶端的 Samba(CIFS)只讀共享
要以只讀共享 sales
,更新 smb.conf
,如下:
[sales]
comment = Sales Data
path = /export/cifs/sales
read only = Yes
guest ok = Yes
關于文件系統表(fstab)
你可以在 Unix/Linux 上的 /etc/fstab
文件中配置掛載某些文件為只讀模式。
你需要有專用分區,不要設置其他系統分區為只讀模式。
如下在 /etc/fstab
文件中設置 /srv/html
為只讀模式。
/dev/sda6 /srv/html ext4 ro 1 1
你可以使用 mount
命令重新掛載分區為只讀模式[2](使用 root 用戶)
# mount -o remount,ro /dev/sda6 /srv/html
或者
# mount -o remount,ro /srv/html
上面的命令會嘗試重新掛載已掛載的文件系統到 /srv/html
上。這是改變文件系統掛載標志的常用方法,特別是讓只讀文件改為可寫的。這種方式不會改變設備或者掛載點。讓文件變得再次可寫,鍵入:
# mount -o remount,rw /dev/sda6 /srv/html
或
# mount -o remount,rw /srv/html
Linux:chattr 命令
你可以在 Linux 文件系統上使用 chattr
命令改變文件屬性為只讀[3],如:
chattr +i /path/to/file.php
TML 中使用 <input> 元素表示單行輸入框和 <textarea> 元素表示多行文本框。
HTML中使用的 <input> 元素在 JavaScript 中對應的是 HTMLInputElement 類型。HTMLInputElement 繼承自 HTMLElement 接口:
interface HTMLInputElement extends HTMLElement {
...
}
HTMLInputElement 類型有一些獨有的屬性和方法:
而在上述介紹 HTMLInputElement 類型中的屬性時,type 屬性要特別關注一下,因為根據 type 屬性的改變,可以改變<input>的屬性。
類型 | 描述 |
text | 文本輸入 |
password | 密碼輸入 |
submit | 表單數據提交 |
button | 按鈕 |
radio | 單選框 |
checkbox | 復選框 |
file | 文件 |
hidden | 隱藏的字段 |
image | 定義圖像作為提交按鈕 |
reset | 重置按鈕 |
省略 type 屬性與 type="text"效果一樣, <input> 元素顯示為文本框。
當 type 的值為text/password/number/時,會有以下屬性對 <input> 元素有效。
屬性 | 類型 | 描述 |
autocomplete | string | 字符串on或off,表示<input>元素的輸入內容可以被瀏覽器自動補全。 |
maxLength | long | 指定<input>元素允許的最多字符數。 |
size | unsigned long | 表示<input>元素的寬度,這個寬度是以字符數來計量的。 |
pattern | string | 表示<input>元素的值應該滿足的正則表達式 |
placeholder | string | 表示<input>元素的占位符,作為對元素的提示。 |
readOnly | boolean | 表示用戶是否可以修改<input>的值。 |
min | string | 表示<input>元素的最小數值或日期。 |
max | string | 表示<input>元素的最大數值或日期。 |
selectionStart | unsigned long | 表示選中文本的起始位置。如果沒有選中文本,返回光標在<input>元素內部的位置。 |
selectionEnd | unsigned long | 表示選中文本的結束位置。如果沒有選中文本,返回光標在<input>元素內部的位置。 |
selectionDirection | string | 表示選中文本的方向。可能的值包括forward、backward、none。 |
下面創建一個 type="text" ,一次顯示 25 個字符,但最多允許顯示 50 個字符的文本框:
<input type="text" size="25" maxlength="50" value="initial value">
HTML 使用的 <textarea> 元素在 JavaScript 中對應的是 HTMLTextAreaElement 類型。HTMLTextAreaElement類型繼承自 HTMLElement 接口:
interface HTMLTextAreaElement extends HTMLElement {
...
}
HTMLTextAreaElement 類型有一些獨有的屬性和方法:
下面創建一個高度為 25,寬度為 5 的 <textarea> 多行文本框。它與 <input> 不同的是,初始值顯示在 <textarea>...</textarea> 之間:
<textarea rows="25" cols="5">initial value</textarea>
注意:處理文本框值的時候最好不要使用 DOM 方法,而應該使用 value 屬性。
<input> 與 <textarea> 都支持 select() 方法,該方法用于選中文本框中的所有內容。該方法的語法為:
select(): void
下面看一個示例:
let textbox = document.forms[0].elements["input-box"];
textbox.select();
也可以在文本框獲得焦點時,選中文本框的內容:
textbox.addEventListener("focus", (event) => {
event.target.select();
});
當選中文本框中的文本或使用 select() 方法時,會觸發 select 事件。
let textbox = document.forms[0].elements["textbox1"];
textbox.addEventListener("select", (event) => {
console.log(`Text selected: ${textbox.value}`);
});
HTML5 對 select 事件進行了擴展,通過 selectionStart 和 selectionEnd 屬性獲取文本選區的起點偏移量和終點偏移量。如下所示:
function getSelectedText(textbox){
return textbox.value.substring(textbox.selectionStart,
textbox.selectionEnd);
}
注意:在 IE8 及更早版本不支持這兩個屬性。
HTML5 提供了 setSelectionRange() 方法用于選中部分文本:
setSelectionRange(start, end, direction): void;
下面看一個例子:
<input type="text" id="text-sample" size="20" value="Hello World!">
<button onclick="selectText()">選中部分文本</button>
<script>
function selectText() {
let input = document.getElementById("text-sample");
input.focus();
input.setSelectionRange(4, 8); // o Wo
}
</script>
如果想要看到選中效果,必須讓文本框獲得焦點。
不同文本框經常需要保證輸入特定類型或格式的數據,或許數據需要包含特定字符或必須匹配某個特定模式。而文本框并未提供驗證功能,因此要配合 JavaScript 腳本實現輸入過濾功能。
有些輸入框需要出現或不出現特定字符。如果想要將輸入框變成只讀的,只需要使用 preventDefault()方法將按鍵都屏蔽:
input.addEventListener("keypress", (event) => {
event.preventDefault();
});
而要屏蔽特定字符,就需要檢查事件的 charCode 屬性。如下所示,使用正則表達式實現只允許輸入數字的輸入框:
input.addEventListener("keypress", (event) => {
if (!/\d/.test(event.key)) {
event.preventDefault();
}
});
還有一個問題需要處理:復制、粘貼及涉及Ctrl 鍵的其他功能。在除IE 外的所有瀏覽器中,前面代碼會屏蔽快捷鍵Ctrl+C、Ctrl+V 及其他使用Ctrl 的組合鍵。因此,最后一項檢測是確保沒有按下Ctrl鍵,如下面的例子所示:
textbox.addEventListener("keypress", (event) => {
if (!/\d/.test(String.fromCharCode(event.charCode)) &&
event.charCode > 9 &&
!event.ctrlKey){
event.preventDefault();
}
});
最后這個改動可以確保所有默認的文本框行為不受影響。這個技術可以用來自定義是否允許在文本框中輸入某些字符。
IE 是第一個實現了剪切板相關的事件以及通過JavaScript訪問剪切板數據的瀏覽器,其它瀏覽器在后來也都支持了相同的事件和剪切板的訪問,后來 HTML5 將其納入了規范。以下是與剪切板相關的 6 個事件:
剪切板事件的行為及相關對象會因瀏覽器而異。在 Safari、Chrome 和 Firefox 中,beforecopy、beforecut 和 beforepaste 事件只會在顯示文本框的上下文菜單時觸發,但 IE 不僅在這種情況下觸發,也會在 copy、cut 和 paste 事件在所有瀏覽器中都會按預期觸發。
在實際的事件發生之前,通過beforecopy、beforecut 和 beforepaste 事件可以在向剪貼板發送或從中檢索數據前修改數據。不過,取消這些事件并不會取消剪貼板操作。要阻止實際的剪貼板操作,必須取消 copy、cut和 paste 事件。
剪貼板的數據通過 clipboardData 對象來獲取,且clipboardData 對象提供 3 個操作數據的方法:
而 clipboardData 對象在 IE 中使用 window 獲取,在 Firefox、Safari 和 Chrome 中使用 event 獲取。為防止未經授權訪問剪貼板,只能在剪貼板事件期間訪問 clipboardData 對象;IE 會在任何時候都暴露 clipboardData 對象。因此,要兼容兩者,最好在剪貼板事件期間使用該對象。
function getClipboardText(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
}
function setClipboardText (event, value){
if (event.clipboardData){
return event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData){
return window.clipboardData.setData("text", value);
}
}
如果文本框只有數字,那剪貼時,就需要使用paste事件檢查剪貼板上的文本是否無效。如果無效,可以取消默認行為:
input.addEventListener("paste", (event) => {
let text = getClipboardText(event);
if (!/^\d*$/.test(text)){
event.preventDefault();
}
});
注意:Firefox、Safari和Chrome只允許在onpaste事件中訪問getData()方法。
在 JavaScript 中,可以用在當前字段完成時自動切換到下一個字段的方式來增強表單字段的易用性。比如,常用手機號分為國家好加手機號。因此,我們設置 2 個文本框:
<form>
<input type="text" name="phone1" id="phone-id-1" maxlength="4">
<input type="text" name="phone2" id="phone-id-2" maxlength="11">
</form>
當文本框輸入到最大允許字符數后,就把焦點移到下一個文本框,這樣可以增加表單的易用性并加速數據輸入。如下所示:
<script>
function tabForward(event){
let target = event.target;
if (target.value.length == target.maxLength){
let form = target.form;
for (let i = 0, len = form.elements.length; i < len; i++) {
if (form.elements[i] == target) {
if (form.elements[i+1]) {
form.elements[i+1].focus();
}
return;
}
}
}
}
let inputIds = ["phone-id-1", "phone-id-2"];
for (let id of inputIds) {
let textbox = document.getElementById(id);
textbox.addEventListener("keyup", tabForward);
}
</script>
這里,tabForward() 函數通過比較用戶輸入文本的長度與 maxLength 屬性的值來檢測輸入是否達到了最大長度。如果兩者相等,就通過循環表中的元素集合找到當前文本框,并把焦點設置到下一個元素。
注意:上面的代碼只適用于之前既定的標記,沒有考慮可能存在的隱藏字段。
HTML5 新增了一些表單提交前,瀏覽器會基于指定的規則進行驗證,并在出錯時顯示適當的錯誤信息。而驗證會基于某些條件應用到表單字段中。
表單字段中添加 required 屬性,用于標注該字段是必填項,不填則無法提交。該屬性適用于<input>、<textarea>和<select>。如下所示:
<input type="text" name="account" required>
也可以通過 JavaScript 檢測對應元素的 required 屬性來判斷表單字段是否為必填項:
let isRequired = document.forms[0].elements["account"].required;
也可以檢測瀏覽器是否支持 required 屬性:
let isRequiredSupported = "required" in document.createElement("input");
注意:不同瀏覽器處理必填字段的機制不同。Firefox、Chrome、IE 和Opera 會阻止表單提交并在相應字段下面顯示有幫助信息的彈框,而Safari 什么也不做,也不會阻止提交表單。
HTML5 為 <input> 元素增加了幾個新的 type 值。如下所示:
類型 | 描述 |
number | 數字值的輸入 |
date | 日期輸入 |
color | 顏色輸入 |
range | 一定范圍內的值的輸入 |
month | 允許用戶選擇月份和年份 |
week | 允許用戶選擇周和年份 |
time | 允許用戶選擇時間(無時區) |
datetime | 允許用戶選擇日期和時間(有時區) |
datetime-local | 允許用戶選擇日期和時間(無時區) |
電子郵件地址的輸入 | |
search | 搜索(表現類似常規文本) |
tel | 電話號碼的輸入 |
url | URL地址的輸入 |
這些輸入表名字段應該輸入的數據類型,并且提供了默認驗證。如下所示:
<input type="email" name="email">
<input type="url" name="homepage">
要檢測瀏覽器是否支持新類型,可以在 JavaScript 中創建 <input> 并設置 type 屬性,之后讀取它即可。老版本中會將我只類型設置為 text,而支持的會返回正確的值。如下所示:
let input = document.createElement("input");
input.type = "email";
let isEmailSupported = (input.type == "email");
而上面介紹的幾個如 number/range/datetime/datetime-local/date/month/week/time 幾個填寫數字的類型,都可以指定 min/max/step 等幾個與數值有關的屬性。step 屬性用于規定合法數字間隔,如 step="2",則合法數字應該為 0、2、4、6,依次類推。如下所示:
<input type="number" min="0" max="100" step="5" name="count">
上面的例子是<input>中只能輸入從 0 到 100 中 5 的倍數。
也可以使用 stepUp() 和 stepDown() 方法對 <input> 元素中的值進行加減,它倆會接收一個可選參數,用于表示加減的數值。如下所示:
input.stepUp(); // 加1
input.stepUp(5); // 加5
input.stepDown(); // 減1
input.stepDown(10); // 減10
HTML5 還為文本添加了 pattern 屬性,用于指定一個正則表達式。這樣就可以自己設置 <input> 元素的輸入模式了。如下所示:
<input type="text" pattern="\d+" name="count">
注意模式的開頭和末尾分別假設有^和$。這意味著輸入內容必須從頭到尾都嚴格與模式匹配。
與新增的輸入類型一樣,指定 pattern 屬性也不會阻止用戶輸入無效內容。模式會應用到值,然后瀏覽器會知道值是否有效。通過訪問 pattern 屬性可以讀取模式:
let pattern = document.forms[0].elements["count"].pattern;
使用如下代碼可以檢測瀏覽器是否支持pattern 屬性:
let isPatternSupported = "pattern" in document.createElement("input");
HTML5 新增了 checkValidity() 方法,用來檢測表單中任意給定字段是否有效。而判斷的條件是約束條件,因此必填字段如果沒有值會被視為無效,字段值不匹配 pattern 屬性也會被視為無效。如下所示:
if (document.forms[0].elements[0].checkValidity()){
// 字段有效,繼續
} else {
// 字段無效
}
要檢查整個表單是否有效,可以直接在表單上調用checkValidity()方法。這個方法會在所有字段都有效時返回true,有一個字段無效就會返回false:
if(document.forms[0].checkValidity()){
// 表單有效,繼續
} else {
// 表單無效
}
validity 屬性會返回一個ValidityState 對象,表示 <input> 元素的校驗狀態。返回的對象包含一些列的布爾值的屬性:
因此,通過 validity 屬性可以檢查表單字段的有效性,從而獲取更具體的信息,如下所示:
if (input.validity && !input.validity.valid){
if (input.validity.valueMissing){
console.log("請指定值.")
} else if (input.validity.typeMismatch){
console.log("請指定電子郵件地址.");
} else {
console.log("值無效.");
}
}
通過指定 novalidate 屬性可以禁止對表單進行任何驗證:
<form method="post" action="/signup" novalidate>
<!-- 表單元素 -->
</form>
也可以在 JavaScript 通過 noValidate 屬性設置,為 true 表示屬性存在,為 false 表示屬性不存在:
document.forms[0].noValidate = true; // 關閉驗證
如果一個表單中有多個提交按鈕,那么可以給特定的提交按鈕添加formnovalidate 屬性,指定通過該按鈕無需驗證即可提交表單:
<form method="post" action="/foo">
<!-- 表單元素 -->
<input type="submit" value="注冊提交">
<input type="submit" formnovalidate name="btnNoValidate"
value="沒有驗證的提交按鈕">
</form>
也可以使用 JavaScript 設置 formNoValidate 屬性:
// 關閉驗證
document.forms[0].elements["btnNoValidate"].formNoValidate = true;
以上總結了 <input> 和 <textarea> 兩個元素的一些功能,主要是 <input> 元素可以通過設置 type 屬性獲取不同類型的輸入框,可以通過監聽鍵盤事件并檢測要插入的字符來控制文本框的內容。
還有一些與剪貼板相關的事件,并對剪貼的內容進行檢測。還介紹了一些 HTML5 新增的屬性和方法和新增的更多的 <input> 元素的類型,和一些與驗證相關的屬性和方法。
隨著網絡的廣泛連接和數據的海量增長,我們面臨著越來越多的安全風險。
國家有關部門為了進一步保護加強信息安全,在《中華人民共和國網絡安全法》中規定,網絡運營者應當按照網絡安全等級保護制度的要求,履行安全保護義務,保障網絡免受干擾、破壞或者未經授權的訪問,防止網絡數據泄露或者被竊取、篡改。
在等級保護規范《GBT 25070-2019 信息安全技術網絡安全等級保護安全設計技術要求》中,明確要求用戶數據完整性保護,可采用常規校驗機制,檢驗存儲的用戶數據的完整性,以發現其完整性是否被破壞。
企業網站是企業的重要數字門戶,網頁防篡改正是為了防止網站內容被惡意篡改破壞,確保網站數據的真實性和完整性,滿足等級保護用戶數據完整性保護要求。
同時,網頁防篡改也有助于維護企業網站聲譽、保障業務正常運行、避免法律責任。
網頁防篡改技術分析
網頁被篡改原因分析
網頁被篡改通常有以下幾種方式:
通過服務器漏洞: 攻擊者利用服務器操作系統或應用程序(如 Web 服務器軟件)的安全漏洞,獲取對服務器的非法訪問權限,進而修改網頁文件。
賬號密碼被竊取: 如果網站管理員或相關賬號的密碼強度不夠或被泄露,攻擊者獲取到這些賬號后,可以登錄到后臺管理系統進行網頁篡改。
惡意軟件感染: 服務器或網站所在的系統感染了惡意軟件,這些惡意軟件可能會修改網頁文件。
網絡連接被劫持: 攻擊者通過網絡劫持技術,在數據傳輸過程中篡改網頁內容。
內部人員篡改: 網站內部的工作人員由于各種原因,故意篡改網頁內容。
要防止網頁被篡改,需要 加強服務器安全防護、定期更新軟件、使用強密碼、加強網絡安全監控 等措施。
網頁防篡改主流方案
對于已經被入侵的系統,如何防止網頁被篡改,主要有以下技術手段:
系統文件過濾驅動: 在操作系統內核層對文件操作進行監控和過濾,實時阻止非法的文件寫入和修改。
事件觸發機制: 設定特定事件(如文件修改事件)觸發檢測和保護動作。
數字水印技術: 在網頁中嵌入數字水印,一旦網頁被篡改,水印信息會發生變化,從而被檢測到。
加密技術: 對網頁文件進行加密,使攻擊者難以直接修改加密后的內容。
完整性校驗技術: 如哈希算法,計算網頁文件的特征值,通過對比特征值來判斷是否被篡改。
本文將介紹在 Amazon Web Services 上,如何使用系統能力以及 Amazon Web Services 提供的服務能力,實現網頁防篡改。
Amazon EC2 篡改防護
如果我們的網站業務直接部署于 Amazon EC2 系統中,為了確保內容不被篡改,最簡單的辦法就是讓系統內文件只讀。 但是只讀后文件無法更新,所以,我們還需要對應的更新方案。
對于掛載后,我們也需要持續的監控文件是否有變化。如果有,要及時發現。
下面我們分別針對 Linux 與 Windows 系統進行介紹。
Amazon EC2 Linux 篡改防護
Amazon EC2 Linux 系統預防篡改
Amazon EC2 Linux 系統創建內容盤。
1.在 Amazon Web Services 控制臺,我們先創建一塊新的 Amazon EBS 硬盤,具體操作流程參考創建 Amazon EBS 卷。 https://docs.amazonaws.cn/zh_cn/ebs/latest/userguide/ebs-creating-volume.html
2.創建成功后,將創建的 Amazon EBS 硬盤,附加到我們的內容服務器,具體流程參考將 Amazon EBS 卷掛載到實例。 https://docs.aws.amazon.com/zh_cn/ebs/latest/userguide/ebs-attaching-volume.html
3.掛載完成后,還需要在 Linux 系統內對 Amazon EBS 卷進行分區、格式化、掛載等操作,具體流程請參考使 Amazon EBS 卷可供使用。 https://docs.amazonaws.cn/zh_cn/ebs/latest/userguide/ebs-using-volumes.html
4.之后,我們就可以使用 Amazon EBS 卷進行讀寫操作,編輯我們的網站內容,編輯完成后,即可對該 Amazon EBS 卷進行快照操作,創建快照的操作參考創建 Amazon EBS 快照。 https://docs.aws.amazon.com/zh_cn/ebs/latest/userguide/ebs-creating-snapshot.html
5.創建好的快照,就是我們后面網站內容的“模版”,通過該快照創建 Amazon EBS,實現內容的發布。
Amazon EC2 Linux 系統只讀掛載。
1.通過之前創建好的快照,創建 Amazon EBS 卷,過程可以參考官方文檔從快照創建卷。 https://docs.amazonaws.cn/zh_cn/ebs/latest/userguide/ebs-creating-volume.html#ebs-create-volume-from-snapshot
2.然后,與前文一致,將 Amazon EBS 卷掛載到實例。
3.掛載完成后,在 Linux 系統內,我們還需要進行加載。為了保護內容,我們采用只讀掛載的方式。
1.# 確保目錄存在
2.sudo mkdir -p /mnt/protect-content
3.# 確保沒有掛載其他盤
4.sudo umount /mnt/protect-content
5.# `/dev/nvm1p1` 更換為實際device node
6.sudo mount -o ro /dev/nvm1p1 /mnt/protect-content
4.掛載完成,只讀的內容即可供外部訪問。由于是只讀掛載,內容不可被修改。
Amazon EC2 Linux 系統內容更新。
未來,我們肯定希望對內容進行更新。更新的流程,與創建內容、只讀掛載發布類似。
1.通過快照創建 Amazon EBS 卷。
2.正常可讀寫方式掛載到內容編輯服務器,在服務器內進行內容編輯。
3.編輯完成,重新制作 Amazon EBS 卷快照。
4.使用新的 Amazon EBS 卷快照,生成新的 Amazon EBS 卷。
5.將原來的 Amazon EBS 卷從實例分離,參考將 Amazon EBS 卷與實例分離。 https://docs.amazonaws.cn/zh_cn/ebs/latest/userguide/ebs-detaching-volume.html
6.只讀方式,掛載新的 Amazon EBS 卷
7.刪除原來的 Amazon EBS 卷,參考刪除 Amazon EBS 卷。 https://docs.amazonaws.cn/zh_cn/ebs/latest/userguide/ebs-deleting-volume.html
Amazon EC2 Linux 系統偵測篡改事件
Inotify 是一種 Linux 內核機制,用于監視文件系統中的事件。它允許應用程序監視文件或目錄的創建、刪除、修改、屬性更改,以及移動或重命名等事件。
Inotify 提供了一種高效且可擴展的方式,來監視文件系統活動,并使其成為各種應用程序的寶貴工具。
Inotify 有多種應用場景,包括:
文件系統監控: inotify 可用于監視文件系統活動,例如文件創建、刪除、修改和重命名。這對于備份應用程序、病毒掃描程序和其他需要監視文件系統活動的應用程序很有用。
桌面通知: inotify 可用于在文件或目錄發生更改時向用戶發送桌面通知。這對于文件共享應用程序、同步工具和其他需要通知用戶文件系統活動的應用程序很有用。
實時事件處理: inotify 可用于實時處理文件系統事件。這對于日志記錄應用程序、審計工具和其他需要實時響應文件系統活動的應用程序很有用。
Inotify 的特性,使得它在文件保護、防篡改方面,是最適合的工具。
下面的示例代碼,可用于監控 Linux 文件變化,在變化的時候通知我們,讓我們能第一時間反應、處理:
1.#include <stdio.h>
2.#include <stdlib.h>
3.#include <sys/inotify.h>
4.#include <unistd.h>
5.#include <fcntl.h>
6.#include <string.h>
7.
8.#define EVENT_SIZE? ( sizeof(struct inotify_event) )
9.#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
10.
11.void handle_event(struct inotify_event *event) {
12.? if (event->len) {
13.? ? // Check for specific events (modify, create, delete)
14.? ? if (event->mask IN_MODIFY) {
15.? ? ? printf("File %s in directory was modified.\n", event->name);
16.? ? } else if (event->mask IN_CREATE) {
17.? ? ? printf("File %s was created in directory.\n", event->name);
18.? ? } else if (event->mask IN_DELETE) {
19.? ? ? printf("File %s was deleted from directory.\n", event->name);
20.? ? }
21.? }
22.}
23.
24.int main(int argc, char *argv[]) {
25.? if (argc != 2) {
26.? ? printf("Usage: %s <directory>\n", argv[0]);
27.? ? exit(1);
28.? }
29.
30.? // Open the inotify instance
31.? int fd = inotify_init();
32.? if (fd == -1) {
33.? ? perror("inotify_init");
34.? ? exit(1);
35.? }
36.
37.? // Add a watch on the specified directory
38.? int wd = inotify_add_watch(fd, argv[1], IN_MODIFY | IN_CREATE | IN_DELETE);
39.? if (wd == -1) {
40.? ? perror("inotify_add_watch");
41.? ? exit(1);
42.? }
43.
44.? char buffer[EVENT_BUF_LEN];
45.
46.? // Continuously read events
47.? while (1) {
48.? ? int nread = read(fd, buffer, EVENT_BUF_LEN);
49.? ? if (nread == -1) {
50.? ? ? perror("read");
51.? ? ? exit(1);
52.? ? }
53.
54.? ? int i = 0;
55.? ? while (i < nread) {
56.? ? ? struct inotify_event *event = (struct inotify_event *) buffer[ i ];
57.? ? ? // Check if event refers to the watched directory (avoid subdirectories)
58.? ? ? if (strcmp(event->name, "") == 0) {
59.? ? ? ? continue; // Skip events for the directory itself (empty name)
60.? ? ? }
61.? ? ? handle_event(event);
62.? ? ? i += EVENT_SIZE + event->len;
63.? ? }
64.? }
65.
66.? // Close inotify instance (would never be reached in this example)
67.? close(fd);
68.
69.? return 0;
70.}
滑動查看更多
通過編譯,執行該代碼,即可實現網頁文件內容變更通知:
1.# 編譯代碼
2.gcc -o inotify inotify.c
3.# 運行監控
4../inotify <dir>
Amazon EC2 Windows 篡改防護
Amazon EC2 Windows 系統預防篡改
Amazon EC2 Windows 只讀掛載防篡改與 Linux 基本一致,差異部分在于如何只讀掛載 Amazon EBS 卷。
1.# 關閉自動掛載
2.mountvol.exe /N
3.# 進入分區管理
4.diskpart
5.# 列出磁盤
6.list volume
7.# 根據上面列出的,選擇分區,替換<X>
8.select volume <X>
9.# 設置分區屬性, readonly
10.attributes volume set readonly
11.# 查看結果
12.detail volume
滑動查看更多
其他的,與前文 Linux 系統內容類似。
Amazon EC2 Windows 系統偵測篡改事件
與 Linux 類似,Windows .NET SDK 提供了 FileSystemWatcher 這個接口。
它是 Windows 中用于監視文件系統活動的 API。它允許應用程序監視文件或目錄的創建、刪除、修改、重命名等事件。
我們可以參考官網的例子,編寫對應的應用來監控變化。 https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-8.0redirectedfrom=MSDN
也可以直接使用一些現有的開源工具, 比如 https://github.com/thekid/inotify-win
Inotify-win 實現了類似 Linux inotify 的功能,通過以下命令,即可實現文件目錄的監控通知:
1.inotifywait.exe -r -m <dir>
Amazon S3 篡改防護
Amazon S3 網站方案
Amazon S3 簡介
Amazon Simple Storage Service(Amazon S3)是一種對象存儲服務,提供行業領先的可擴展性、數據可用性、安全性和性能。
各種規模和行業的客戶都可以使用 Amazon S3 存儲和保護任意數量的數據,用于數據湖、網站、移動應用程序、備份和恢復、歸檔、企業應用程序、IoT 設備和大數據分析。
可以使用 Amazon S3 托管靜態網站,還可以將 Amazon S3 與內容分發網絡(CDN)(如 Amazon CloudFront)結合使用來交付網頁。
Amazon S3 作為 Website 先決條件
在將自定義域配置為在 Amazon Web Services 中國(寧夏)區域托管 Amazon S3 靜態網站之前,必須滿足以下先決條件。
取得 ICP 備案
如果域名通過 Amazon Web Services 中國(寧夏)區域中,由寧夏西云數據科技有限公司(NWCD)運營的服務器進行公共訪問,必須通過 NWCD 申請 ICP 備案。
配置 Amazon S3 靜態網站
1.創建域存儲桶和可選的子域存儲桶:
對于域存儲桶,啟用靜態網站托管,然后上傳網站內容。啟用靜態網站托管后,域存儲桶會被分配一個 Amazon S3 網站端點,例如 www.example.com.cn.s3-website.cn-north-1.amazonaws.com.cn,使用此網站端點配置 Amazon Route 53 自定義域。
對于子域存儲桶,在靜態網站托管下,為對象配置重定向請求,以重定向至上傳到域存儲桶的網站內容。
域存儲桶包含構成網站的文件,子域存儲桶會將請求重新路由到域存儲桶。例如,如果客戶進入 www.example.com.cn,子域存儲桶會將請求轉發到域存儲桶:example.com.cn。
2.清除所有四種 Amazon S3 屏蔽公共訪問權限設置,以便可以添加允許對存儲桶進行公共讀取訪問的存儲桶策略。
3.添加允許對存儲桶進行公共讀取訪問的存儲桶策略,將網站暴露給外部進行訪問。
使用 Amazon Route 53 配置自定義域
完成在 Amazon S3 中配置靜態網站后,就有了網站端點,假設為 www.example.com.cn.s3-website.cn-north-1.amazonaws.com.cn(www.example.com.cn),可以將自定義域名映射到此端點,并通過自定義域訪問網站。
要為域和子域配置別名記錄,請按照以下步驟操作:
1.通過以下網址打開 Amazon Route 53 控制臺: https://console.aws.amazon.com/route53/
2.請選擇托管區域。
3.在托管區域列表中,請選擇與域名匹配的托管區域的名稱。
4.要為托管區創建別名記錄,請選擇創建記錄。
5.請選擇切換到向導。
6.選擇簡單路由,然后選擇下一步。
7.選擇定義簡單記錄。
對于記錄名稱,接受默認值。
對于記錄類型,選擇 CNAME 將流量路由到另一個域名和某些 Amazon Web Services 資源。
對于值/流量路由至,選擇根據記錄類型選擇 IP 地址或其他值。在文本框中,輸入 Amazon S3 網站端點:s3-website.cn-north-1.amazonaws.com.cn。
選擇定義簡單記錄。
8.通過自定義域名(例如 http://example.com.cn)訪問網站,以驗證網站和重定向是否有效。
通過 Amazon CloudFront 建立加速緩存
Amazon CloudFront 是 Amazon Web Services 上的 CDN 服務,它可以將 Amazon S3 設置為分發的對象,將 Amazon S3 上的資源,通過 Amazon Web Services 分布在邊緣節點將內容提供給用戶。
同時,Amazon CloudFront 還提供了 Amazon S3 不支持的 HTTPS 協議,讓前端應用更加安全。然而由于 Amazon Web Services 中國(寧夏)區域的一些特殊情況,在此使用 Amazon S3 + Amazon CloudFront,需要一些不同于 Global 的額外配置。
1. 建立 Amazon S3 數據桶。
注意:需要設置阻止公開訪問。
2. 建立 Amazon Route 53。
紅框內輸入已備案的域名。
3. 建立 Amazon CloudFront 分配。
源選擇存放前端資源的 Amazon S3 桶,桶中如果沒有子文件夾,則留空源路徑輸入框,來源訪問選擇“遺留訪問身份”,點擊“建立新的 OAI”,下面選擇“否,我將更新存儲桶策略”。
在備用域名中,添加剛才在 Amazon Route 53 添加的域名,默認根對象填寫 index.html (根 HTML 文件文件名)。
建立完成后,進入“源”標簽頁,記下 Origin access 的值,如圖紅框所示:
4. 更新 Amazon S3 桶策略并保存。
代碼如下(替換{$ORIGIN_ACCESS_ID}和BUCKET_ARN/*):
1.{
2.? ? "Version": "2012-10-17",
3.? ? "Statement": [
4.? ? ? ? {
5.? ? ? ? ? ? "Effect": "Allow",
6.? ? ? ? ? ? "Principal": {
7.? ? ? ? ? ? ? ? "AWS": "arn:aws-cn:iam::cloudfront:user/CloudFront Origin Access Identity {$ORIGIN_ACCESS_ID}"
8.? ? ? ? ? ? },
9.? ? ? ? ? ? "Action": "s3:GetObject",
10.? ? ? ? ? ? "Resource": “BUCKET_ARN/*"
11.? ? ? ? }
12.? ? ]
13.}
滑動查看更多
5. 回到 Amazon Route 53,增加別名。
如果實用子域名,則需要新增 CNAME 記錄,并在 Amazon CloudFront 的備用域名中,輸入該記錄的完整域名。
全部完成后,等待片刻,即可去設定的域名測試效果。
Amazon S3 網站預防內容篡改
Amazon S3 對象版本
Amazon S3 中的版本控制,是在相同的存儲桶中保留對象的多個版本的方法。對于存儲桶中存儲的每個對象,可以使用 Amazon S3 版本控制功能來保留、檢索和還原它們的各個版本,從而達到防止被篡改的效果。
啟用了版本控制的存儲桶,可以恢復因意外或被外部惡意刪除操作而被篡改的對象。例如,如果刪除對象,Amazon S3 會插入刪除標記,而不是永久刪除該對象。
存儲桶擁有者和所有獲得授權的 Amazon IAM 用戶,都可以啟用版本控制。
版本 ID
如果為存儲桶啟用版本控制,Amazon S3 會自動為要存儲的對象生成唯一版本 ID。例如,在一個存儲桶中,可以擁有兩個具有相同鍵(對象名稱)的對象,但版本 ID 不同,例如 photo.gif(版本 111111)和 photo.gif(版本 121212)。
無論 Amazon S3 版本控制是否啟用,每個對象都有一個版本 ID。
如果未啟用 Amazon S3 版本控制,Amazon S3 將版本 ID 的值設置為 null。如果啟用 Amazon S3 版本控制,Amazon S3 會為對象分配版本 ID 值。此值將該對象與同一個鍵的其他版本區分開來。
在現有存儲桶上啟用 Amazon S3 版本控制時,已存儲在存儲桶中的對象將保持不變。版本 ID(null)、內容和權限保持不變。啟用 Amazon S3 版本控制后,添加到存儲桶的每個對象都會獲得一個版本 ID,該 ID 將此版本與同一個鍵的其他版本區分開來。
版本控制工作流程
當在啟用版本控制的存儲桶中,通過 PUT 放入對象時,不會覆蓋非當前版本。如下圖所示,當將 photo.gif 的新版本 PUT 到一個已經包含同名對象的存儲桶中時,會發生以下行為:
原始對象(ID = 111111)保留在存儲桶中。
Amazon S3 生成一個新的版本 ID(121212),并將這個較新版本的對象添加到存儲桶中。
使用此功能,如果對象被意外覆蓋或刪除,則可以檢索對象的先前版本。
當 DELETE 對象時,所有版本都將保留在存儲桶中,而 Amazon S3 將插入刪除標記,如下圖所示:
刪除標記將成為對象的當前版本。默認情況下,GET 請求將檢索最新存儲的版本。在當前版本為刪除標記時,執行 GET Object 請求將返回 404 Not Found 錯誤,如下圖所示:
但是,可以通過指定對象版本 ID,通過 GET 獲取非當前版本的對象。在下圖中,GET 特定對象版本 111111。即使該對象版本不是當前版本,Amazon S3 也會返回它。
有關更多信息,請參閱從啟用了版本控制的存儲桶中檢索對象版本。 https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/RetrievingObjectVersions.html
可以通過指定要刪除的版本來永久刪除對象。只有 Amazon S3 存儲桶的擁有者或者授權的 Amazon IAM 用戶,才能永久刪除某個版本。如果 DELETE 操作指定了 versionId,則會永久刪除該對象版本,Amazon S3 不會插入刪除標記。
可以通過配置存儲桶,來啟用多重身份驗證(MFA)刪除,從而提升安全性。 對存儲桶啟用 MFA 刪除時,存儲桶擁有者,必須在任何請求中包含兩種形式的身份驗證,以刪除版本或更改存儲桶的版本控制狀態。
在存儲桶上啟用版本控制
在 Amazon S3 存儲桶上,啟用或禁用版本控制:
1.登錄到 Amazon Web Services Management Console。
2.在存儲桶列表中,請選擇要為其啟用版本控制的存儲桶的名稱。
3.請選擇屬性。
4.在存儲桶版本控制下,請選擇編輯。
5.請選擇 Suspend (暫停) 或 Enable (啟用),然后選擇 Save changes (保存更改)。
Amazon S3 使用對象鎖
一次寫入多次讀
Amazon S3 Object Lock 是 Amazon S3 的一項功能, 允許使用一次寫入、多次讀取(WORM)模式存儲對象, 可以在數據寫入后不得更改或刪除的情況下,使用 WORM 保護,使用此功能無需支付額外費用。
Amazon S3 Object Lock 提供兩種管理對象保留的方法, 第一種是保留期,第二種是合法保留。
保留期規定了對象保持鎖定狀態的固定時間段。在此期間,對象受 WORM 保護,不能被覆蓋或刪除。保留期的單位可以是天數,也可以是年數,最短為 1 天,沒有最長限制。
合法保留提供的保護與保留期相同,但沒有過期日期。相反,合法保留會一直存在,直到明確將其移除。
使用 Amazon S3 對象鎖,可以防止對象在固定時間內被刪除或覆蓋,或直到合法保留被移除。一個對象版本可以同時具有保留期和合法保留。
Amazon S3 偵測對象內容變更
在對對象做了相應的安全保護手段之后,最后我們還需要具備偵測的能力,即當對象真的被篡改之后,可以收到相應的通知,以及時采取后續策略。
我們可以利用 Amazon S3 的事件功能結合 Amazon SNS 服務,將通知發送到運維或相關人員的郵箱、微信等其他應用。
目前, Amazon S3 可以發布用于以下事件的通知:
新的對象創建事件
對象移除事件
還原對象事件
低冗余存儲 (RRS) 對象丟失事件
復制事件
Amazon S3 生命周期到期事件
Amazon S3 生命周期轉換事件
Amazon S3 Intelligent-Tiering 自動歸檔事件
對象標記事件
對象 ACL PUT 事件
本文以對象被移除并發布郵件通知為例進行說明。
對象內容變化監控架構:
當托管在 Amazon S3 當中的靜態網頁被移除時(篡改),配置好的 Amazon S3 事件會偵測到這個動作,并且通過 Amazon SNS 服務將通知發送給訂閱好的郵箱。
實現過程
1.上傳托管的靜態文件。
2.創建 Amazon SNS 通知主題。
這里需要注意的是,為了讓 Amazon S3 event 具有可以調用 Amazon SNS API 的權限,需要配置 topic 的 access policy,按照如下樣例進行配置:
1.{
2.? ? "Version": "2012-10-17",
3.? ? "Id": "example-ID",
4.? ? "Statement": [
5.? ? ? ? {
6.? ? ? ? ? ? "Sid": "Example SNS topic policy",
7.? ? ? ? ? ? "Effect": "Allow",
8.? ? ? ? ? ? "Principal": {
9.? ? ? ? ? ? ? ? "Service": "s3.amazonaws.com"
10.? ? ? ? ? ? },
11.? ? ? ? ? ? "Action": [
12.? ? ? ? ? ? ? ? "SNS:Publish"
13.? ? ? ? ? ? ],
14.? ? ? ? ? ? "Resource": "SNS-topic-ARN",
15.? ? ? ? ? ? "Condition": {
16.? ? ? ? ? ? ? ? "ArnLike": {
17.? ? ? ? ? ? ? ? ? ? "aws:SourceArn": "arn:aws:s3:*:*:bucket-name"
18.? ? ? ? ? ? ? ? },
19.? ? ? ? ? ? ? ? "StringEquals": {
20.? ? ? ? ? ? ? ? ? ? "aws:SourceAccount": "bucket-owner-account-id"
21.? ? ? ? ? ? ? ? }
22.? ? ? ? ? ? }
23.? ? ? ? }
24.? ? ]
25.}
滑動查看更多
3.使用郵箱訂閱主題,完成后的郵箱會收到郵件確認,點擊鏈接后完成訂閱主題。
4.在屬性標簽配置 Amazon S3 事件,創建事件通知。
5.配置事件通知參數。
選擇之前創建的 Amazon SNS 主題。
6.測試刪除文件后,是否能捕獲通知。
總結
本文介紹在 Amazon Web Services 上,如何在 Amazon EC2 Linux/Windows 系統、Amazon S3 網站托管,實現網頁防篡改。
在 Amazon EC2 系統中,可以通過 Amazon EBS Snapshot 只讀掛載實現,同時,通過 inotify 機制實現監控;在 Amazon S3,可以通過對象鎖、對象版本實現只讀,通過 Amazon Lambda 實現 Amazon S3 變更事件的通知與自動化處理。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。