☰
Windows服务器IIS站点部署与DNS域名解析排错指南
2026/10/28 18:12:10 网站建设 项目流程

简介:面向 IT 运维人员与 Windows 服务器初学者的实操型文档,围绕 Windows Server 2022 Web 服务器的搭建与配置展开,可用于课程实验、企业建站入门及日常运维参考。压缩包内共 1 个 docx 文件,约 1016KB,以图文文档形式系统梳理服务器安装、功能测试、网站挂载以及网址与 IP 地址的域名解析等核心环节,便于按章节查阅和对照练习。已有 2769 人学习下载,说明内容具备一定的实用性与参考价值。文档重点呈现 Web 服务从环境准备到站点上线的完整流程,并涉及端口配置、DNS 记录配置与解析测试等关键知识点,适合希望快速建立整体认知、梳理搭建思路或查漏补缺的读者使用。

1. 从裸机到浏览器跳出首页:windows 服务器这条链路要打通四段

要让一台 windows 服务器对外吐出一个网页,本质上要打通四段链路:系统装好、IIS 角色装好、站点目录和绑定配对、域名解析指对。任意一段断掉,浏览器看到的都是白屏、403 或者 404,很多人就在这四段里来回猜,改一处刷一次页面,一天下来也没定位到卡点在哪。下面按实际动手顺序拆:从 Server 2022 的安装形态怎么选,到 IIS 角色服务勾哪几个,再到端口绑定冲突怎么绕、DNS 正向反向记录怎么填,最后给一套从本机到跨机、从 IP 到域名的验证动作。适合刚接手 windows 服务器、要把课程设计或者内网演示站挂上去的读者,也适合已经装过 IIS 但总在 403 和端口占用上翻车的人。

2. IIS 角色装完不等于站点能跑:角色服务勾选与站点目录落地

装完 IIS、浏览器打开http://localhost看到那张欢迎页,很多人就以为大功告成。结果把网站素材往目录里一拷、绑定一改,页面立刻变成 403 或者 500,回头怀疑是不是装漏了什么。问题基本不在 IIS 本体,而在三处默认值和站点实际需求对不上:角色服务少勾了默认文档或者静态内容,站点目录的 NTFS 权限没给 IIS 的工作账户,应用程序池的运行时版本和站点类型不匹配。这一章按「装什么、放哪、谁有权读、谁是默认页」四件事逐层落地。

2.1 先定安装形态:桌面体验和 Server Core 的账要算清楚

Server 2022 装的时候有两类主要形态,带桌面体验的完整安装和 Server Core。课程设计、内网演示、需要打开图形化 IIS 管理器一项项点着配的场景,选桌面体验,省事;纯跑静态站、只做反向代理或者用远程管理工具连过去维护的场景,Server Core 体积小、补丁面窄、重启少,但它没有本地图形界面,IIS 管理器得从另一台机器远程连或者全靠 PowerShell 的 WebAdministration 模块。新手一上来选 Core,最常见的结果是连站点目录都不会建,卡在第一步。

安装介质准备好之后,挂载 ISO 从虚拟光驱引导,语言和时区按实际选,安装类型选「自定义」,磁盘按需分区。系统盘给 60G 以上比较稳,日志和站点素材分开放到数据盘。装完首次登录会强制改 Administrator 密码,改完先别急着装 IIS,把计算机名和静态 IP 定下来,后面 DNS 记录要跟这个 IP 对得上。

# 确认网卡名称,下面所有命令里的 InterfaceAlias 都要和这里一致 Get-NetAdapter | Where-Object Status -eq 'Up' | Select-Object Name, InterfaceIndex, LinkSpeed # 配静态 IP,网关按实际网段改 New-NetIPAddress -InterfaceAlias 'Ethernet0' -IPAddress 192.168.10.20 -PrefixLength 24 -DefaultGateway 192.168.10.1 # DNS 先指向自己,等 DNS 角色装好后再确认这条没被覆盖 Set-DnsClientServerAddress -InterfaceAlias 'Ethernet0' -ServerAddresses '192.168.10.20'

New-NetIPAddress里-PrefixLength 24就是子网掩码 255.255.255.0 的另一种写法,写错这一位会出现「IP 配上了但网关不通」的典型现象。Set-DnsClientServerAddress建议在装 DNS 角色之前就先跑一遍,避免后面客户端解析时还去问外网 DNS,绕一圈回不来。

2.2 用一条命令把 IIS 和角色服务勾全

图形界面里加角色是一路下一步,但角色服务那一页的勾选项有几十个,漏一个就是后面某个 404。用 PowerShell 显式列出来更可控,也方便把这串命令存成脚本复用。

# 以管理员身份运行,显式列出需要的角色服务,比 -IncludeAllSubFeature 干净 $features = @( 'Web-Server', # IIS 核心 'Web-WebServer', # Web 服务器 'Web-Common-Http', # 常见 HTTP 功能 'Web-Default-Doc', # 默认文档,缺了会 403.14 'Web-Dir-Browsing', # 目录浏览,调试期开着方便看文件在不在 'Web-Http-Errors', # HTTP 错误页 'Web-Static-Content', # 静态内容,html/css/js/图片全靠它 'Web-Http-Redirect', # HTTP 重定向 'Web-Health', # 健康与诊断 'Web-Http-Logging', # 访问日志 'Web-Log-Libraries', # 日志库 'Web-Request-Monitor', # 请求监视 'Web-Performance', # 性能 'Web-Stat-Compression', # 静态内容压缩 'Web-Security', # 安全性 'Web-Filtering', # 请求筛选 'Web-App-Dev', # 应用开发 'Web-Net-Ext45', # .NET 扩展性 4.5 'Web-Asp-Net45', # ASP.NET 4.5 'Web-ISAPI-Ext', # ISAPI 扩展 'Web-ISAPI-Filter', # ISAPI 筛选器 'Web-Mgmt-Tools', # 管理工具 'Web-Mgmt-Console' # IIS 管理控制台,缺了开始菜单里找不到 ) Install-WindowsFeature -Name $features -IncludeManagementTools

Install-WindowsFeature是 Server 2022 自带的部署映像服务模块命令,装系统角色不需要连外网,源就在本地组件存储里。数组里任何一个名字拼错,整条命令会报「找不到功能」并整体回滚,不会装一半,所以报错时先盯名字,别去怀疑系统。-IncludeManagementTools会把对应的管理控制台一起装上。

装完用下面这条核对,InstallState全是Installed才算过:

Get-WindowsFeature -Name Web-* | Where-Object InstallState -eq 'Installed' | Select-Object Name, InstallState | Sort-Object Name

顺手把服务状态也看一眼,W3SVC是 World Wide Web 发布服务,它没起来,站点状态一定是停止:

Get-Service W3SVC, WAS | Select-Object Name, Status, StartType

2.3 站点目录、权限与应用程序池

目录这块有个血泪经验:不要把站点根目录放在桌面、下载目录或者C:\Users下面。这些位置默认继承了用户配置文件那一套复杂权限,IIS 的工作账户进不去,排查起来又绕。规规矩矩在数据盘建一个独立目录。

# 建站点根目录 $siteRoot = 'D:\WebSites\demo' New-Item -Path $siteRoot -ItemType Directory -Force # 把素材整体拷进去,注意是拷「内容」不是拷「素材文件夹本身」 Copy-Item -Path 'E:\素材\*' -Destination $siteRoot -Recurse -Force # 确认入口文件存在,名字后面要和默认文档配置对上 Get-ChildItem $siteRoot -Filter 'index.*' | Select-Object Name, Length

拷完素材紧接着授权限。IIS 里默认应用程序池用的是ApplicationPoolIdentity,它表现为一个虚拟账户,实际访问文件系统时落在IIS_IUSRS组里,所以给这个组授「读取和执行」就够跑静态站,不要图省事给Everyone完全控制。

# (OI)(CI) 表示对象继承和容器继承,RX 是读取和执行 icacls "D:\WebSites\demo" /grant "IIS_IUSRS:(OI)(CI)(RX)" /T

再建应用程序池和站点。应用程序池是把不同站点的进程隔离开的容器,一个池崩了不连带别的站,生产上一般一站一池。

Import-Module WebAdministration # 建独立应用程序池,运行时版本按站点类型选 New-WebAppPool -Name 'demoPool' Set-ItemProperty 'IIS:\AppPools\demoPool' -Name managedRuntimeVersion -Value 'v4.0' Set-ItemProperty 'IIS:\AppPools\demoPool' -Name enable32BitAppOnWin64 -Value $false # 建站点,端口先用 8080 避开默认站点的 80,后面再调 New-Website -Name 'demo' -PhysicalPath 'D:\WebSites\demo' ` -ApplicationPool 'demoPool' -Port 8080 -HostHeader '' -Force

managedRuntimeVersion填v4.0表示用 .NET Framework 4.x 的运行时,纯静态站其实填v2.0或者留空也能跑,但填v4.0更通用,后面要放 ASP.NET 页面不用再改。enable32BitAppOnWin64设成$false表示只跑 64 位进程,如果站点里带的是 32 位编译的 DLL,这里要改成$true,否则会出现「应用程序池启动失败、站点 503」的经典现象,事件日志里能看到模块加载失败的记录。

最后把默认文档补上。IIS 的默认文档列表里自带Default.htm、index.htm、iisstart.htm,但很多素材包的入口叫index.html,不在列表里,请求根路径时就落到 403.14。

# 把 index.html 追加到该站点的默认文档列表 Add-WebConfiguration -Filter '/system.webServer/defaultDocument/files' ` -PSPath 'IIS:\Sites\demo' -Value @{value='index.html'} # 核对该站点默认文档顺序 Get-WebConfigurationProperty -PSPath 'IIS:\Sites\demo' ` -Filter 'system.webServer/defaultDocument' -Name files | Select-Object -ExpandProperty Collection | Select-Object value

这里-PSPath 'IIS:\Sites\demo'是关键,不加这个参数改的是全局默认文档,会把整台机器上所有站点都动一遍,后面别的站点行为变了都不知道为什么。习惯上凡是Add-WebConfiguration、Set-WebConfigurationProperty这类命令,都把-PSPath精确指到站点级别。

做到这一步,本机浏览器访问http://localhost:8080应该能看到首页。看不到就先去第 4 章按顺序排查,别急着往下配 DNS,站点本身没通,解析配得再对也是白搭。

3. 端口、绑定与 DNS:把 IP 访问变成域名访问

站点用 IP 加端口能访问,只能算半成品。真实交付里对方要的是「输入域名就能打开」,中间差着两件事:IIS 的绑定信息要把主机头带上,DNS 要有能把域名翻成 IP 的记录。这两件事各自都不复杂,麻烦的是它们出错时表现高度相似——浏览器都打不开,用户都说是「网站挂了」,不按层拆很难定位。这一章先讲绑定的三个字段和端口冲突的来源,再落 DNS 服务的安装、正向反向区建立和客户端验证。

3.1 绑定的三个字段,以及端口为什么不能重复

IIS 里每个站点的一组绑定由三个字段组成:IP 地址、端口、主机头。三个字段合起来唯一确定一次请求该落到哪个站点。默认站点占着*:80:,你在同一台机器上再建一个站点也绑*:80:且主机头留空,两者完全重叠,IIS 会直接拒绝启动新站点,事件日志里出现「另一个站点正在使用同一端口」之类的记录,站点状态是停止。

先用命令把所有站点现有绑定拉出来看一遍,比在图形界面里一个个点开快得多:

# 列出全部站点的绑定信息,bindingInformation 的格式是 IP:端口:主机头 Get-WebBinding | Select-Object ItemXPath, protocol, bindingInformation | Format-Table -AutoSize

改绑定的方式是先删再建,比直接在原对象上改字段稳:

# 移除端口 8080 的旧绑定 Remove-WebBinding -Name 'demo' -Protocol 'http' -Port 8080 # 重建绑定:IP 用 * 表示任意地址,端口 8080,主机头 demo.local New-WebBinding -Name 'demo' -Protocol 'http' -Port 8080 ` -HostHeader 'demo.local' -IPAddress '*'

-IPAddress '*'表示监听本机所有网卡地址,内网演示场景够用;如果机器有多块网卡、只想在某一块上暴露,就把星号换成具体 IP。-HostHeader填了之后,只有请求头里的 Host 匹配demo.local才会落到这个站点,用 IP 直接访问反而会 404。这是很多人配完主机头后「IP 能开、域名打不开」的第一反应点,其实方向反了,是域名能开、IP 打不开。

端口选择上有个硬约束:同一 IP 加同一端口的组合只能被一个不带主机头的站点独占。所以默认站点在跑的情况下,第二个站点要么换端口,要么保留 80 但给不同主机头。课程设计、内网演示这类场景,用非标准端口加主机头是最省事的组合。

提示:改完绑定后站点不会自动重启,执行iisreset /noforce或者单独重启应用程序池再测,否则测到的可能还是旧配置。

3.2 装 DNS 角色,把域名翻成 IP

DNS 服务器角色和 IIS 可以在同一台机器上,内网演示场景这样最省资源。装角色的命令很短:

# 装 DNS 服务器角色并带上管理工具 Install-WindowsFeature -Name DNS -IncludeManagementTools # 确认服务在跑 Get-Service DNS | Select-Object Name, Status, StartType

服务起来之后建正向查找区域。区域名就是你要用的域名后缀,内网随便定一个不冲突的就行,比如demo.local。动态更新设成None,避免客户端自己往区里写记录把手工建的记录搅乱。

# 建正向查找区域 Add-DnsServerPrimaryZone -Name 'demo.local' -ZoneFile 'demo.local.dns' -DynamicUpdate 'None' # A 记录:demo.demo.local 指向服务器内网 IP,换成你实际配的地址 Add-DnsServerResourceRecordA -Name 'demo' -ZoneName 'demo.local' -IPv4Address '192.168.10.20' # CNAME:让 www.demo.local 也指过来,运维上比再建一条 A 记录好维护 Add-DnsServerResourceRecordCName -Name 'www' -HostNameAlias 'demo.demo.local' -ZoneName 'demo.local' # 反向查找区,让 IP 能反查回名字,排错时省一轮问人 Add-DnsServerPrimaryZone -Name '10.168.192.in-addr.arpa' ` -ZoneFile '10.168.192.in-addr.arpa.dns' -DynamicUpdate 'None' Add-DnsServerResourceRecordPtr -Name '20' -ZoneName '10.168.192.in-addr.arpa' ` -PtrDomainName 'demo.demo.local'

Add-DnsServerResourceRecordA里的-Name 'demo'是相对名,最终记录是demo.demo.local,别写成完整域名,会变成demo.demo.local.demo.local。反向区的命名规则是从 IP 段倒着写,192.168.10.0/24对应10.168.192.in-addr.arpa,PTR 记录的-Name '20'就是主机位,最终反查结果是20.10.168.192.in-addr.arpa指向demo.demo.local。反向区不是必须的,但排错阶段nslookup 192.168.10.20能直接回出名字,比对着 IP 猜是哪个站快。

3.3 客户端指向 DNS、清缓存、放行防火墙

服务器自己的 DNS 配好了,客户端还得知道去问谁。把客户端网卡的 DNS 指到这台服务器,然后清缓存验证,三步走:

# 客户端上执行:把 DNS 指向服务器 Set-DnsClientServerAddress -InterfaceAlias 'Ethernet0' -ServerAddresses '192.168.10.20' # 清本机 DNS 缓存,改了记录不清缓存是最常见的「明明改了没生效」 Clear-DnsClientCache # 验证解析结果 Resolve-DnsName -Name 'demo.demo.local' -Type A -Server 192.168.10.20

-Server参数指定直接问哪台 DNS,绕开本机缓存和其他配置,这一步能排除掉一大半「客户端配置有问题」的干扰。返回里IPAddress是192.168.10.20就说明解析链路通了。

防火墙这一关经常被忽略。Server 2022 默认开启防火墙,入站规则里 IIS 只预置了 80 端口的规则,你换到 8080 就没这条规则了。DNS 的 53 端口通常是装角色时自动加的,但换过网络配置文件(公用/专用)之后可能不生效。

# 放行 8080 的 HTTP 入站,Profile 限定在域和专用网络 New-NetFirewallRule -DisplayName 'IIS-HTTP-8080' -Direction Inbound ` -Protocol TCP -LocalPort 8080 -Action Allow -Profile Domain,Private # 确认 DNS 53 端口的规则存在 Get-NetFirewallRule -DisplayName '*DNS*' | Select-Object DisplayName, Enabled, Profile

-Profile Domain,Private限定只在域网络和专用网络生效,公用网络不放行。有人图省事直接把整块防火墙关掉,实验环境里看着没事,换到真实网段上就是敞开大门,这个习惯不建议带出去。

4. 避坑排查:站点起不来时按这五条顺序看

前面几步里任何一个没落到位,表现都是「打不开」,但具体日志和状态码完全不同。把下面五条按顺序走一遍,基本能定位到具体是哪一层断的。顺序是从服务到网络再到应用,跳着查容易在错误的方向上耗时间。

4.1 现象:站点状态显示「已停止」,事件日志里报端口冲突

原因:同一 IP 加同一端口上已经有一个不带主机头的站点在监听,新站点的绑定和它完全重叠,IIS 拒绝启动。或者端口被别的进程先占了,比如装了第三方 Web 服务或者调试工具。

解决:先用Get-WebBinding比对所有站点的端口和主机头,重叠的换端口或者补主机头。再确认端口有没有被非 IIS 进程占着:

# 看 8080 到底被谁占用,OwningProcess 是 PID Get-NetTCPConnection -LocalPort 8080 -State Listen | Select-Object LocalAddress, LocalPort, OwningProcess # 用 PID 反查进程名 Get-Process -Id (Get-NetTCPConnection -LocalPort 8080 -State Listen).OwningProcess

如果占用者不是System(IIS 的 HTTP.sys 在内核态,通常显示 System 或 PID 4),那就是真冲突,换端口最直接。

4.2 现象:本机http://localhost能开,隔壁机器打不开

原因:八成本机防火墙没放行对应端口,或者站点绑定只监听在127.0.0.1而不是*。还有一种情况是站点绑了主机头,本机用 localhost 访问走的是默认站点,所以「看起来能开」。

解决:先在服务器上用Test-NetConnection测自己,再用客户端测服务器,两头对齐:

# 服务器上执行,确认端口在本机监听正常 Test-NetConnection -ComputerName 127.0.0.1 -Port 8080 -InformationLevel Detailed # 客户端上执行,确认跨机可达 Test-NetConnection -ComputerName 192.168.10.20 -Port 8080 -InformationLevel Detailed

TcpTestSucceeded为False而本机那条为True,问题就在防火墙或中间网络设备上,跟站点配置无关。

4.3 现象:403.14 Forbidden,目录结构看着没问题

原因:请求的是目录路径(比如站点根/),IIS 找不到匹配的默认文档,又没开目录浏览,直接返回 403.14。素材入口文件名不在默认文档列表里是最常见的一类。

解决:先确认文件真的在,再补默认文档,顺序别反:

# 确认入口文件存在 Get-ChildItem 'D:\WebSites\demo' -Filter 'index.*' # 补默认文档到站点级 Add-WebConfiguration -Filter '/system.webServer/defaultDocument/files' ` -PSPath 'IIS:\Sites\demo' -Value @{value='index.html'}

调试期可以临时开目录浏览确认文件都在,但交付前记得关掉,把整个人站点目录列给访客看不是个好习惯:

Set-WebConfigurationProperty -PSPath 'IIS:\Sites\demo' ` -Filter 'system.webServer/directoryBrowse' -Name enabled -Value $true

4.4 现象:域名 ping 不通,但 IP 能直接访问站点

原因:客户端 DNS 没指向服务器,或者指向了服务器但区域里记录的相对名写错,再或者改完记录客户端缓存没清。排错阶段还有一个高频干扰项:客户端 hosts 文件里留着一条旧记录,优先级高于 DNS,怎么改服务器都不生效。

解决:用-Server参数绕开一切本地配置直接问服务器,返回正确说明客户端配置或缓存的问题:

# 直接问服务器,绕开本机缓存 Resolve-DnsName -Name 'demo.demo.local' -Type A -Server 192.168.10.20 # 清缓存后再问 Clear-DnsClientCache ipconfig /flushdns # 按域名反查 IP nslookup demo.demo.local 192.168.10.20

如果-Server指定后能解析、不指定就解析不了,问题一定在客户端的 DNS 指向或 hosts 文件上,去查网卡设置和C:\Windows\System32\drivers\etc\hosts。

4.5 现象:静态页正常,ASP.NET 页面报 500.19

原因:500.19是配置错误,最常见的是站点目录下的web.config引用了没装的角色服务(比如 URL 重写模块),或者应用程序池的运行时版本和web.config里声明的版本不匹配。还有一种是被requestFiltering拦了特定扩展名。

解决:先看详细错误页里Config Error那一行指向哪个节点,再去补对应的角色服务。应用程序池版本这块直接对着改:

# 查应用程序池的运行时和位数设置 Get-ItemProperty 'IIS:\AppPools\demoPool' | Select-Object name, managedRuntimeVersion, enable32BitAppOnWin64 # 按站点实际需要调整 Set-ItemProperty 'IIS:\AppPools\demoPool' -Name managedRuntimeVersion -Value 'v4.0' Set-ItemProperty 'IIS:\AppPools\demoPool' -Name enable32BitAppOnWin64 -Value $false

改完应用程序池要回收一次才生效,Restart-WebAppPool -Name 'demoPool',别只刷新页面。

5. 验证与进阶:一套从本机到跨机的检查顺序

站点配完之后最容易犯的错,是把「站点问题」和「解析问题」混在一起查。我后来固定成一个顺序:服务层、本机端口、HTTP 层、跨机端口、DNS 层,一层不通就停在这一层,不往下走。这个顺序的好处是每层都有明确的成功判据,不用靠猜。

# 第 1 层:服务在不在 Get-Service W3SVC, WAS, DNS | Select-Object Name, Status # 第 2 层:本机端口通不通 Test-NetConnection -ComputerName 127.0.0.1 -Port 8080 -InformationLevel Quiet # 第 3 层:HTTP 响应头正不正常,200 之外的状态码直接暴露问题类型 curl.exe -I http://127.0.0.1:8080/ # 第 4 层:跨机端口通不通,这一步要在客户端上跑 Test-NetConnection -ComputerName 192.168.10.20 -Port 8080 -InformationLevel Quiet # 第 5 层:DNS 解析对不对,显式指定服务器 Resolve-DnsName -Name 'demo.demo.local' -Type A -Server 192.168.10.20 # 第 6 层:反向解析,排错时确认 IP 归属 Resolve-DnsName -Name '192.168.10.20' -Type PTR -Server 192.168.10.20

第 3 层的curl.exe -I在 Server 2022 上是自带的,不用装额外组件,返回头里的Server:字段还能看出响应到底是 IIS 给的还是别的服务给的。返回403说明请求到站点了但被拒,返回404说明站点对了路径不对,503基本就是应用程序池没起来。这几种状态码对应到第 4 章的哪一条,比反复重启服务高效得多。

进阶用法里最值得掌握的是多站点共用 80 端口。一台 windows 服务器上挂两个演示站,都绑*:80:,靠主机头区分:

# 两个站点同端口,靠主机头路由 New-WebBinding -Name 'demo' -Protocol 'http' -Port 80 -HostHeader 'demo.local' -IPAddress '*' New-WebBinding -Name 'demo2' -Protocol 'http' -Port 80 -HostHeader 'demo2.local' -IPAddress '*'

IIS 靠请求头里的 Host 字段决定落到哪个站点,所以两个域名都要有对应的 DNS 记录。这里有个容易忽略的边界:用 IP 直接访问 80 端口时,没有 Host 头匹配任何站点,IIS 会回落到默认站点,看到的页面可能完全不是你以为的那个。交付前用不同域名和 IP 各测一遍,能避免甲方现场演示时打开错页面的尴尬。

最后一个习惯,从那以后我每建一个站点,都先在本机 hosts 文件里写一行192.168.10.20 demo.demo.local,确认页面能出来,再去动 DNS。顺序反了,站点和解析两边一起查,能把人熬到半夜。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询