CentOS7搭建NAS文件共享存儲


一、安裝

服務端安裝nfs-utils、rcpbind軟件包;

yum -y install nfs-utils rpcbind

二、配置

2.1 通過nfs協議配置nas

vi /etc/sysconfig/nfs

設置各種*port=...參數

# TCP port rpc.lockd should listen on.
LOCKD_TCPPORT=32803
# UDP port rpc.lockd should listen on.
LOCKD_UDPPORT=32769

# Port rpc.statd should listen on.
STATD_PORT=662
# Outgoing port statd should used. The default is port
# is random
STATD_OUTGOING_PORT=2020

既然涉及到端口, 就要確保防火牆沒有屏蔽以上端口, 否則的話, 客戶端和服務器端無法建立連接. 
NAS在這里充當了NFS服務器的角色,而Linux,Solaris和AIX則是NFS客戶機。NFS的功能很多,不同的功能對應着不同的daemon。比如一定要有的nfsd和mountd,還有可選的lockd和statd。
每個daemon都需要占用一些端口,但有些daemon是可選的,也許用戶根本不會啟用它們。所以,NFS並沒有給每個NFS daemon保留固定端口(除了nfsd)。而是在系統啟動時給需要啟用的NFS daemon分配端口,然后把這些端口號告訴RPC daemon。RPC daemon的端口號是固定的111,每個NFS客戶機都知道怎么聯系它。當客戶機需要連接NFS的某個daemon時,就不得不先咨詢RPC daemon,獲得該NFS daemon對應的端口號,然后再發送NFS請求。
我第一次看到RPC daemon的工作原理,就想起交大管浴室的老頭。他的固定地址是門房(相當於端口111),每個要洗澡的學生(NFS客戶機)都知道怎么找到他,他會給你一個帶號碼的鑰匙(端口號),有了這個號碼,你就可以找到相應的格子(NFS daemon)放衣服了。
很少有人會對自己的共享不加限制,像我一樣收獲小電影的畢竟是少數,大多數人收獲的是惡作劇。NFS通過限制客戶機(比如IP地址, hostname等)訪問來實現安全控制。下表列舉了一些NFS服務器端的端口:

端口號 服務
32803/32769 服務
662 status
111 portmapper
20048 mountd
2049 nfs/nfs_acl

來看連接的建立過程

1)首先服務器端啟動RPC服務,並開啟111端口

2)服務器端啟動NFS服務,並向RPC注冊端口信息

3)客戶端啟動RPC(portmap服務),向服務端的RPC(portmap)服務請求服務端的NFS端口

4)服務端的RPC(portmap)服務反饋NFS端口信息給客戶端。

5)客戶端通過獲取的NFS端口來建立和服務端的NFS連接並進行數據的傳輸。

舉例:

   當服務器端, 啟動了rpcbind 和 nfs 這兩個服務后, 我們查看服務器端網絡狀況.

$sudo netstat -lntp
tcp        0      0 0.0.0.0:2049            0.0.0.0:*               LISTEN      -      

tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      614/rpcbind  
tcp        0      0 0.0.0.0:20048           0.0.0.0:*               LISTEN      910/rpc.mountd 
tcp        0      0 0.0.0.0:662             0.0.0.0:*               LISTEN      877/rpc.statd 

rpcbind:

它響應RPC服務的請求和與請求的RPC服務建立連接

nfs
  最主要的NFS服務提供程序,這個daemon主要的功能就是管理客戶端是否能夠使用服務器文件系統掛載信息,其中還包含判斷這個登錄用戶的ID。

rpc.mountd
  這個daemon主要功能則是管理NFS的文件系統。當client端順利通過rpc.nfsd登入主機后,在它可以使用NFS服務器提供規定文件之前,還會經過文件使用權限的認證程序。它會去讀取NFS的配置  文件/etc/exports來對比客戶端的權限,當通過這一關之后,client端也就取得使用NFS文件的權限。

rpc.statd(非必要)
  這個daemon可以用來檢查文件的一致性,若發生因為客戶端同時使用同一個文件造成文件損壞時,rpc.statd可以用來檢測並嘗試恢復該文件

可以看到, rpcbind 監聽在111端口,  nfs監聽在2049 端口.

我們在使用rpcinfor -p 查看nfs的服務時, 會看到nfs注冊了以下服務, 

 1 rpcinfo -p
 2 
 3 
 4 program vers proto port service
 5 100000 4 tcp 111 portmapper
 6 100000 3 tcp 111 portmapper
 7 100000 2 tcp 111 portmapper
 8 100000 4 udp 111 portmapper
 9 100000 3 udp 111 portmapper
10 100000 2 udp 111 portmapper
11 100005 1 udp 20048 mountd
12 100005 1 tcp 20048 mountd
13 100024 1 udp 662 status
14 100024 1 tcp 662 status
15 100005 2 udp 20048 mountd
16 100005 2 tcp 20048 mountd
17 100005 3 udp 20048 mountd
18 100005 3 tcp 20048 mountd
19 100003 3 tcp 2049 nfs
20 100003 4 tcp 2049 nfs
21 100227 3 tcp 2049 nfs_acl
22 100003 3 udp 2049 nfs
23 100003 4 udp 2049 nfs
24 100227 3 udp 2049 nfs_acl
25 100021 1 udp 32769 nlockmgr
26 100021 3 udp 32769 nlockmgr
27 100021 4 udp 32769 nlockmgr
28 100021 1 tcp 32803 nlockmgr
29 100021 3 tcp 32803 nlockmgr
30 100021 4 tcp 32803 nlockmgr
View Code

假設我們現在以vi編輯器打開並修改某個以nfs方式掛載至客戶機的文件t的文件test.txt 

客戶端portmap 首先向服務器端的111端口發起請求, 詢問nfs服務的端口號, 服務端portmap會反饋2049, 客戶端立即通過2049端口與服務端建立鏈接.

建立鏈接后, 服務端進一步發送訪問test.txt的請求, 服務段經過nfs_acl鑒權, 如果用戶有權限訪問, 則放行請求, 否則提示權限不足, 由於是寫文件, 需要通過nlockmgr獲得文件鎖, 否則等待鎖釋放.

 

 

 

 

2.2 配置要共享的文件

創建共享目錄:

mkdir /shared
chmod 777 /shared

注意:初次配置NAS 建議將權限設置為777, 有助於順利測試后續的掛載, 測試讀取,創建,刪除,修改文件, 但是這樣設置是有安全風險的, 后續熟悉了用戶身份映射再回來設置合適的權限. 另外此處我以root用戶身份創建的/shared目錄, 所有共享目錄的owner也是root, 后續等弄明白了身份映射, 也建議回頭把owner改為合適的owner. 當前階段因為權限設置為了777, Owner也不是重點, 不影響將整個流程走通.

 

配置共享目錄細節:

sudo vi /etc/exports
#添加如下內容
/shared 192.168.0.0/16(rw,root_squash,all_squash,sync,anonuid=1000,anongid=1000)

 

加載NFS配置

sudo exportfs -r

初次看到這么一長串其實挺令人費解的, 這些都是什么鬼, 除了rw比較熟悉一點,猜也能猜出來是可讀寫以外, 其他都是一頭霧水.

這里其實不必太糾結, 直接設置為最開放的權限 /shared *(rw) 繼續往后走好了, 后續也不會遇到一些莫名其妙的問題, 把流程走通最重要, 后續再回頭來將設置調精細, 尤其是初次配置NAS, 這樣設置可以避免很多坑, 以免將自己弄得很沮喪.

當你回頭來調參數的時候,就需要了解以下內容了.

第一點: NAS 客戶端是不需要登陸即可訪問共享目錄的, 哪服務器端如何知道訪問者是誰,訪問者該擁有多大權限的呢?

答案就是通過ip 地址和客戶端的當前用戶id, 和組id , 通過IP 控制是否能訪問NAS服務, 通過用戶ID控制能訪問什么文件, 有多大權限, 當然這種簡單的權限控制模型會有缺陷, 要做到相對安全也要看個人的配置能力,以及對NFS的理解程度.

這里我在/etc/exports文件中指定的是一個網段192.168.0.0/16, 什么意思呢? 也就是這個網段的用戶可以訪問NAS上的此目錄, 當然也可以按單個ip地址配置, 可以將網段替換為ip地址, 這樣就只有指定ip地址的用戶可以訪問共享目錄這樣就精細化了很多, 當然 ip地址是容易偽裝, 替換, 以及變化的, 這就是NAS 權限控制比較理想化的地方, 如果是在局域網內,就看管理員如何控制好ip地址的分配, 路由設置等水平了, 所以安不安全要看管理員的水平. 這里也可以配置為通配符, 例如 *, 任何ip過來的用戶都可以訪問.

剛剛講到了 ip 地址是NAS 權限控制的重要因子, 另外客戶端uid, gid 也是權限控制的重要因子, NAS很好的利用了Linux的權限管理模型,  對熟悉Linux/Unix的系統的用戶也降低了學習難度. 首先假設這里配置是no_root_squash, no_all_squash, 這兩個選項是什么意思? 先簡單介紹這兩個選項的作用, 就是不要做身份映射, 簡單來說就是, 如果客戶端當前是 root用戶, 那么他訪問共享目錄的身份就是root, (當然是不是 root 用戶是取決於他的用戶id, 而不是用戶名, 我們知道所有的linux root 用戶的ID都是0, 所屬組ID是0, 這里為了便於描述使用用戶名代表root用戶) , 如果是普通用戶 例如zhangsan (uid:999), 那么他操作共享目錄的身份就是zhangsan, 那么張三有什么樣的權限呢? 還記得我們創建共享目錄的時候設置了什么樣的訪問權限嗎? chmod 777 /shared, 張三不是owner, 不屬於root組, 張三應該屬於others(其他用戶) , others對該目錄用戶讀寫執行權限. 假設我們創建共享目錄的時候是這樣 chmod 770 /shared, 那么張三是沒有任何權限, 對目錄中的文件及文件夾不能進行任何操作. 這就是我為什么在創建共享目錄的時候建議大家先授予目錄777權限, 權限似乎大的嚇人, 但是后續就好發現它的好處, 因為我們在客戶端配置,測試的時候, 往往可能就是其他用戶, 不是root, 也不屬於root的用戶, 尤其在windows上訪問NAS.

從以上的描述, 不知道各位看官有沒有發現一個問題或者叫漏洞( 我擔心在本已很復雜的邏輯,再引入一個復雜的問題, 會讓人暈掉,所以前面只字未提這個, 現在另起一段來討論這個問題). 這里先假設客戶端有個叫zhangsan(uid:999) 的用戶, 服務器端也有zhangsan(uid:999) 的用戶, 那很好啊,客戶端的張三就像服務器端的張三一樣讀或寫共享目錄.接下來的問題就復雜一些了, 假設服務器端壓根就沒有 zhangsan(uid:999) 的用戶, 連uid為999的用戶都沒有, 那會怎樣? 大家可以把流程走通后自己測試一下, 我已經測試過了, 張三依然能訪問目錄, 而且當張三創建新文件的時候, 會創建一個uid:999的文件, 當我ls -lt 查看此文件的時候, 只能看到文件的 owner是999, 不會顯示owner的名字, 如果再進一步使用服務器端用戶訪問此文件, 如果服務器端的 umask 是0022 除了root 沒有一個用戶能查看,修改或刪除它. 這樣其實帶來一個好處, 只有客戶端用戶能訪問他所創建的文件, 如果我們嚴格限制服務器端的 root權限, 理想狀況下能很好的保護客戶端用戶的隱私.

另起一段, 讓事情再復雜一些, 假設服務器上沒有zhangsan(uid:999) 這個用戶, 只有有李四lisi(uid:999) 這個用戶, 那么會怎樣? 此時, 張三創建的文件, 會顯示 owner 是李四(lisi), 如果這個文件里面有張三的隱私的話, 那么張三的隱私有可能被泄露, 如果是錢的哈, 有可能被轉走. 這很不安全,NAS為我們留下了一個巨大的安全漏洞, 也給我們提供了解決辦法, 那么怎么防止這一點呢, linux 也可以做到, 這就需要研究ACL權限控制了, 這里不做展開.

以上不算最嚴重的情況, 畢竟服務器端, 惡意篡改的可能性相對比較小, 也容易控制. 下面這種情況就比較糟糕了, 假設現在有多個客戶端可以訪問共享目錄, 這些客戶機上分別有 李四 lisi(uid:999)  王五 wangwu(uid:999), 趙六zhaoliu(uid:999) , 那么他們都能看到彼此創建的文件, 如果是隱私或保密數據, 那將是是糟糕的不能再糟糕的一件事情. 難道隱私數據就不能放在NAS上嗎? 之前說了, 這取決於管理員的配置水平, NAS權限配置可以精細到單個ip級別, 不同的ip只能訪問到不同的目錄, ip+uid 可以讓用戶彼此隔離開來, 或者引入LDAP, 單點登錄, 讓不同的用戶擁有不同的uid也能防止重復的問題, 而且可以很好的結合LDAP身份驗證功能. 但是任何事物都有兩面性, 假設架設NAS的目的就是為了分享, 為了協同工作, 那么這種設置又能很容易的達到目的. 所以NAS的權限管理可以很靈活, 也可以做到很嚴謹, 也可能很糟糕, 取決於使用目的以及管理水平.

講了這么多, 才講完了no_root_squash, no_all_squash 兩個選項, 是不是超級復雜? 這就完了嗎? 當然還沒有完, 因為權限控制問題本身就很復雜, 在任何一個系統中都是邏輯最復雜最混亂的一塊.  當我們試圖解決客戶端uid重復的時候, 有沒有發現一個新的問題, 問題一, 如果按ip+uid 唯一映射共享目錄, 可以做到很好的隔離, 但是配置文件會膨脹的非常快, 會相當混亂, 維護起來會相當困難, 復雜性轉移到了配置管理了, 有沒有?  問題二, 如果采用LDAP, 客戶端uid可以實現唯一, 但是我們知道任何客戶端的東西都可能被惡意篡改, 難免有不懷好意的用戶, 那么我們必須把控制權掌握在自己手中, 不給惡意使用者留下機會. 那要怎么辦呢? 這里就是身份映射閃亮登場的時候了. 為什么需要身份映射. 

剛剛說了, 在以隱私保護,數據安全為導向的權限設置中,最大的威脅是uid重復. 這里我們引入了LDAP, 也就引入了身份驗證, 也盡量避免uid重復, 但是防止不了偽造. 我們也知道NAS 沒有引入身份驗證的功能, 盡量保持簡便靈活. 既然沒有引入身份驗證, 理論上是不能很好的做到數據隔離的, 更何況我們也有數據共享的必要,協作的必要. 引入身份驗證可能使得協助,共享變得困難,復雜. 既然不能保證全體用戶的隔離, 我們還是能保證部分敏感用戶是隔離的. 假設我們以保護張三的隱私為最高優先級, 那么王五趙六的為次優先級. 那么我們就可以把王五趙六映射為nfsnobody, 張三的映射到全服務器上唯一的一個用戶上, 這樣就避免了張三與其他用戶uid沖突的問題, 服務器端嚴格限制張三對於的uid的權限, 除了root可以訪問,盡量不讓其他用戶訪問張三的隱私數據. 當然如果root用戶要作惡, 技術手段是很難防止的了得, 只有通過行政手段,法律措施, 規章制度來保證.

這應該就是引入 root_squash, all_squash, anonuid, anongid的目的, 要搞懂這些選項, 先要弄懂這幾個單詞的含義很重要, squash 這里采用的是壓扁的意思, 想象一下網絡上的用戶(趙錢孫李,周吳鄭王) 像潮水一遍的向NAS涌來, 在進入nas服務之前, 將他們壓縮,壓扁成一個用戶nfsnobody(nfs小人物) 當我們在服務器上安裝nfs-utils的時候,默認就會創建一個nfsnobody用戶, 如果我們不想使用nfsnobody, 或者一個nfsnobody根本不夠用, 我們可以使用 anonuid 指定映射身份. root_squansh 表示無論那個客戶端來的root壓扁成nfsnobody, all_squash 表示無論哪個客戶端來的普通用戶壓扁成服務器上的nfs小人物, 那么大人物是誰? 就是那些以真實身份訪問服務器的用戶, 他們的隱私應該得到更好的保護. anonuid  中的anon 就是anonym匿名或無名的縮寫(a是否定前綴, nonym跟name同源, 相當於中文的無名), uid 則對於 linux uid (user id), 這樣這些選項就容易理解, 不容易配錯了. sync選項與權限無關,是用來控制內存數據和硬盤數據是否同步, 要深入了解這個選項, 就要進一步了解Linux 的IO模型, 網絡傳輸協議了, 此處不做展開.

 

2.3 配置NFS相關服務

2.3.1 設置開機啟動

systemctl enable rpcbind
systemctl enable nfs
systemctl enable nfs-lock
systemctl enable nfs-idmap

2.3.2 啟動服務

systemctl start rpcbind
systemctl start nfs
systemctl start nfs-lock
systemctl start nfs-idmap

 

2.3.3 查看端口占用,以便開着防火牆的時候設置

rpcinfo -p
program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100005    1   udp  20048  mountd
    100005    1   tcp  20048  mountd
    100005    2   udp  20048  mountd
    100005    2   tcp  20048  mountd
    100005    3   udp  20048  mountd
    100005    3   tcp  20048  mountd
    100024    1   udp    662  status
    100024    1   tcp    662  status
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   udp   2049  nfs_acl
    100021    1   udp  32769  nlockmgr
    100021    3   udp  32769  nlockmgr
    100021    4   udp  32769  nlockmgr
    100021    1   tcp  32803  nlockmgr
    100021    3   tcp  32803  nlockmgr
    100021    4   tcp  32803  nlockmgr

 

2.4 NAS文件名字符集問題

前面分析了, 客戶端uid不一致可能和服務器端不一致, 會帶來很多安全問題. 下面討論一下客戶端與服務器端字符集不一致可能導致的問題. 客戶端的字符集可能千奇百怪, 服務器端只能設置一種字符集, 如何以不變應萬變呢?  首先我們要搞清楚文件在計算機中是如何存儲的, 也不用太深入, 起碼要弄明白兩個概念, inode, block. 我們經常會見到亂碼的問題, 尤其是文件名, 當然如果內容是文本文件, 當使用文本編輯器打開的時候也會遇到亂碼的問題, 如果是binary文件, 給機器讀取的,到是不必太過擔心. 下面我們來分析一下, 為什么會遇到亂碼問題. 文件名是存儲在inode中的, 二進制數據在傳輸的過程中, 理論上是不會改變的, 如果客戶端是GBK編碼的二進制信息, 服務器收到的后會原樣保存, 如果客戶端和服務器端字符編碼不一致, 這時候服務器端可能看起來就是亂碼. 這種情況下, 只是NAS 管理員看到文件名很迷糊, 客戶端沒影響, 這不影響客戶的使用, 但是影響管理員的管理工作, 試想如果管理員要給文件移動一個位置, 面對一堆亂碼, 確實是很頭疼的一件事.

這里讓問題再復雜一些, 假設現在有兩個客戶端同時能訪問, 編輯同一個共享文件, 他們的編碼方式還不一樣, 那么甲保存的文件名, 乙看起來可能就是亂碼. 乙修改后甲看起來就是亂碼, 如果兩個人脾氣不好, 有可能打起來, 如果兩人都比較溫和內向, 也有可能心生怨恨. 這里個人覺得沒有什么很好的辦法徹底解決亂碼的問題, 只有一些折中的方案, 第一點, 盡量不要使用中文命名文件, 不是萬不得已盡量不要使用中文來命名文件. 第二點, 服務器端和客戶斷盡量使用utf8編碼, 畢竟他支持的中文字符要全面, 也支持其他各國文字, 唯一的缺點是部分中文字符需要四個字節來存儲, 大部分中文常用字符也需要二到三個字節來存儲,  考慮到現在計算機的存儲相對便宜, cpu的速度很快, 大多數情況都不飽和, 如果你的系統對存儲,對性能要求不是十分的苛刻, 服務器端盡量使用utf8, 做到對盡量多的字符提供支持. 客戶端如果能統一編碼方式為utf8那是最好, 如果不能只能告訴客戶端很抱歉, 我們只能做到這種地步了, 最多能在提供一個工具在客戶端轉碼吧, 畢竟utf8編碼還可以嗅探出編碼格式, 如果是其他編碼格式, 可能無能為力. 如果你有更好的解決方案, 歡迎在下方留言.

 

inode 存儲了如下信息:

inode包含文件的元信息,具體來說有以下內容:
  * 文件的字節數
  * 文件擁有者的User ID
  * 文件的Group ID
  * 文件的讀、寫、執行權限
  * 文件的時間戳,共有三個:ctime指inode上一次變動的時間,mtime指文件內容上一次變動的時間,atime指文件上一次打開的時間。
  * 鏈接數,即有多少文件名指向這個inode
  * 文件數據block的位置

例如我們使用stat命令查看一個文件的inode信息, 我特意創建了一個中文命名的文件, 現在假設服務器上使用的是utf-8編碼, 客戶端是GBK編碼, 那么客戶端看到的文件名就可能是亂碼.

[root@i-mywts1aa test]# stat 測試.txt
File: ‘測試.txt’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 25h/37d Inode: 250655 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-11-18 02:36:02.309190000 +0800
Modify: 2020-11-18 02:36:02.309190000 +0800
Change: 2020-11-18 02:36:02.309190000 +0800
Birth: -

三, 客戶端安裝與設置

3.1 Linux客戶端

安裝必要軟件

yum -y install nfs-utils
showmount -e 192.168.1.13   //192.168.1.13 為nfs 服務器ip
 
        

 

單次手動掛載,創建目錄,修改權限:

創建掛載點:
mkdir /mnt/data
chmod 777 /mnt/data        //此處權限需要根據實際情況調整, 777 權限過於開放
掛載:

mount -t nfs 192.168.1.13:/shared /mnt/data

查看掛載:

#df -h

文件系統 容量 已用 可用 已用% 掛載點
devtmpfs 898M
0 898M 0% /dev
tmpfs 910M
0 910M 0% /dev/shm
tmpfs 910M
9.6M 901M 2% /run
tmpfs 910M
0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root 47G 8.5G 39G 18% /
/dev/sda1 1014M 150M 865M 15% /boot
tmpfs 182M
0 182M 0% /run/user/0
192.168.1.13:/shared 27G 2.4G 25G 9% /mnt/data

卸載

umount /mnt/data

開機自動掛載

修改/etc/fstab, 添加一條

192.168.1.13:/shared  /data  nfs  defaults,_rnetdev  1  1

備注:第1個1表示備份文件系統,第2個1表示從/分區的順序開始fsck磁盤檢測,0表示不檢測。

_rnetdev  表示主機無法掛載直接跳過,避免無法掛載主機無法啟動

 

3.2 Windows客戶端

Windows下面默認沒有mount,需要添加功能。

比如Windows 10:(備注: windows 10家庭版除外,家庭版不帶nfs功能, 需要專業版或企業版 )

設置->應用->程序和功能->啟用或關閉Windows功能:勾選上NFS服務

 

很多博客都講了windows上如何掛載 但是沒有講如何取消掛載

刪除可以使用圖形界面取消, 也可以使用umount 命令 例如:

用法: umount [-f] <-a | drive_letters | network_mounts>

umount G:

-a 刪除所有 NFS 網絡裝入點
-f 強制刪除 NFS 網絡裝入點

四, 遇到的坑

clnt_create: RPC: Port mapper failure – Timed out

STATD_OUTGOING_PORT=2020

原因:端口被防火牆屏蔽, 

解決辦法: 設置防火牆,接收來自nfs各端口的上行請求

五, 參考文檔:

https://www.cnblogs.com/cash/p/13433978.html

https://blog.51cto.com/yttitan/2406403

http://blog.chinaunix.net/uid-1829236-id-3242030.html

http://www.360doc.com/content/12/0830/10/21412_233142313.shtml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM