通配符子域名

20
我知道之前有几个关于这个问题的线程,但我已经尝试了所有建议(我能找到的),到目前为止还没有任何作用...
考虑到这一点,这就是我要做的事情:
首先,我想允许用户发布页面并为它们每个选择一个子域(例如:user.example.com)。从我所了解的情况来看,最好的方法是使用mod_rewrite和.htaccessuser.example.com映射到example.com/user - 这正确吗?
如果正确,有人可以给我明确的说明如何做到这一点吗?
另外,我正在本地进行所有开发工作,使用MAMP,因此如果有人告诉我如何设置我的本地环境以同样的方式工作(我已经阅读过这更加困难),我将非常感激。老实说,我已经尝试了所有办法都不行,由于这是我第一次做这样的事情,我完全迷失了方向。
一些答案非常有帮助,但对于我设想中的系统,手动为每个用户添加子域不是一个选项。我真正想问的是如何动态生成子域,并将wildcard.example.com重定向到example.com/wildcard - Tumblr设置的方式是我想要做到的完美范例。

https://dev59.com/qHI_5IYBdhLWcg3wBuNs - Chris Stryczynski
8个回答

16
关于如何设置 DNS 子域名通配符,这取决于你的 DNS 托管提供者。这与你使用的托管提供者有关,具体步骤也会不同,建议向他们咨询。
一旦在 DNS 主机中设置好了,从网页应用程序中,你只需进行 URL 重写即可。可以通过 Web 服务器本身的某些模块来实现,例如如果你使用 IIS,则可以使用 isapi rewrite(如果可能的话,这将是首选)。你也可以在应用程序级别上处理重写(例如在 ASP.NET 中使用路由)。
你需要将 URL 重写,使得 http://myname.example.com 变成 http://example.com/something.aspx?name=myname 或其他类似的形式。从那时起,你只需像处理常规查询字符串一样处理 myname 值即可。
我并不建议为每个用户创建子域名,而是为域名本身创建一个通配符子域名,因此 anything.example.com (基本上是 *.example.com)都指向你的站点。我已经在 MyDomain 上设置了几个域名。他们的设置方法如下:

是的,你可以配置通配符,但它只能在 A 记录中使用。通配符不能在 CNAME 记录中使用。要使用通配符,请使用星号 '' 字符。例如,如果你使用通配符创建 A 记录,*.example.com 中的星号可以是任何东西,并将解析到指定的 IP 地址。因此,如果在域名名称之前输入“www”、“ftp”、“site”或其他任何内容,它都将始终解析到该 IP 地址。

我有一些设置方式与此相同的站点,使用*.example.com访问我的网站。然后在我的 Web 应用程序中读取基本 URL,以查看当前访问的是 ryan.example.com 还是 bill.example.com。接着,我可以执行以下操作之一:

  1. 使用 URL 重写使子域成为查询字符串的一部分 OR
  2. 仅读取已访问 URL 的主机值,并根据该值执行一些逻辑。

这样讲清楚了吗?我有几个站点都是按照这种方式设置的:使用 DNS 主机创建域的通配符,然后只需从 URL 中读取主机或基本域即可根据子域(实际上是用户名)决定要显示什么。

编辑2:

没有 DNS 条目就无法做到这一点。"在线世界" 需要知道 name1.example.comname2.example.com、......、nameN.example.com 都指向您服务器的 IP 地址。唯一能做到这一点的方法是使用相应的 DNS 条目。必须使用 DNS 主机为您的域添加通配符 DNS 条目。然后,只需从 URL 中读取子域并在代码中执行相应的操作即可。


14

如果您正在运行 *AMP,最好按照Thomas的建议在Apache中使用虚拟主机。您可以选择使用或不使用您所描述的重定向来实现此操作。

虚拟主机

最可能您会想要做 基于名称的虚拟主机,因为它是最容易设置的,而且只需要一个IP地址(因此也很容易在本地MAMP机器上进行设置和测试)。基于IP的虚拟主机在其他方面更好,但您必须为每个域名拥有一个IP地址。

这个维基百科页面讨论了区别,并链接到底部的一个良好的基本操作步骤,介绍如何创建基于名称的虚拟主机。

在您的本地机器上进行测试时,您还需要在/etc/hosts中设置假的DNS名称以进行测试域名。例如,如果您在localhost上监听Apache并在您的Apache配置中设置了vhost1.test.domain和vhost2.test.domain,则只需将这些域名添加到/etc/hosts中127.0.0.1行之后的localhost即可:

127.0.0.1 localhost vhost1.test.domain vhost2.test.domain

一旦您完成了对/etc/hosts文件的编辑,并将基于名称的虚拟主机配置添加到您的Apache配置文件中,那就可以了。重新启动Apache,您的测试域名应该就能工作了。

使用mod_rewrite进行重定向

如果您想使用mod_rewrite进行重定向(以便user.example.com没有直接托管,而是重定向到example.com/user),那么您还需要进行RewriteCond来匹配子域并将其重定向:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^subdomain\.example\.com
RewriteRule ^(.*)$ http://example.com/subdomain$1 [R]

你可以将这个代码放在 .htaccess 文件中或者在你的主要 Apache 配置文件中。

对于每个想要重定向的子域名,你需要添加一对像最后两个规则那样的规则。或者,你可以在 RewriteCond 中捕获子域名,以便能够使用一个通配符规则来将 *.example.com 重定向到 example.com/

  • -- 不过从安全角度来看,我觉得这样会有风险。

虚拟主机和重定向

最好是更加明确并设置每个你想监听的主机名的虚拟主机配置部分,并将每个主机名的重写规则放在其虚拟主机配置内部。如果可能的话,将这些东西放在 Apache 配置文件而不是 .htaccess 中总是更安全、更快的 -- .htaccess 会减慢性能,因为 Apache 不断地扫描文件系统寻找 .htaccess 文件并重新解析它们,而且它更不安全,因为用户可能把它们搞砸。

像下面这样,在你的 Apache 配置文件中的虚拟主机配置将是:

NameVirtualHost 127.0.0.1:80

# Your "default" configuration must go first
<VirtualHost 127.0.0.1:80>
  ServerName example.com
  ServerAlias www.example.com
  DocumentRoot /www/siteroot
  # etc.
</VirtualHost>

# First subdomain you want to redirect
<VirtualHost 127.0.0.1:80>
  ServerName vhost1.example.com
  RewriteEngine On
  RewriteRule ^(.*)$ http://example.com/vhost1$1 [R]
</VirtualHost>

# Second subdomain you want to redirect
<VirtualHost 127.0.0.1:80>
  ServerName vhost2.example.com
  RewriteEngine On
  RewriteRule ^(.*)$ http://example.com/vhost2$1 [R]
</VirtualHost>

7

我知道我回答这个问题已经有些晚了,但是我遇到了同样的问题,也需要一个本地开发解决方案。在另一个SO线程中,我找到了更好的解决方案,想要分享给将来有同样问题的人:

VMware拥有的通配符域名可将任何子域名解析为127.0.0.1:

vcap.me resolves to 127.0.0.1
www.vcap.me resolves to 127.0.0.1

或者为了更多的灵活性,37 Signals拥有一个域名,可以使用特定格式将任何子域名映射到任何给定的IP地址:
127.0.0.1.xip.io resolves to 127.0.0.1
www.127.0.0.1.xip.io resolves to 127.0.0.1
db.192.168.0.1.xip.io resolves to 192.168.0.1

请查看xip.io获取更多相关信息。

4

我在Ubuntu 16.04上,自从14.04以来,我一直在使用Dave Evans提供的解决方案(这里),对我来说效果很好。

  1. Install dnsmasq

    sudo apt-get install dnsmasq
    
  2. Create new file localhost.conf under /etc/dnsmasq.d dir with the following line

    #file /etc/dnsmasq.d/localhost.conf
    address=/localhost/127.0.0.1
    
  3. Edit /etc/dhcp/dhclient.conf and add the following line

    prepend domain-name-servers 127.0.0.1;
    

    (You’ll probably find that this line is already there and you just need to uncomment it.)

  4. Last one is restart the service

    sudo systemctl restart dnsmasq
    sudo dhclient
    
最后,您需要检查它是否正常工作。
dig whatever.localhost

注意:

如果您希望在您的Web服务器上使用它,您需要将127.0.0.0更改为您实际的IP地址。


我按照您的指示操作了,但问题是每当应用设置后我的互联网就会断开。我已经在http://stackoverflow.com/questions/42857061/wordpress-multisite-setup-as-subdomain-wildcard-dns-record-setup上发布了我想要实现的内容。请问我该如何做? - Subrata Sarkar
很抱歉,不过我并没有遇到任何配置问题,甚至我的互联网也出了问题。 - Fery W
这个解决方案解决了我的问题。有点奇怪,我通常会跳过第三步,但现在我必须编辑dhclient.conf文件。谢谢老兄,你又节省了我的时间。 :) - Mokhamad Rofi'udin

1

我在我的一个网站上也必须完全做同样的事情。您可以按照以下步骤进行操作

  1. 如果您的服务器上有cPanel,请创建一个子域名*,如果没有,则必须在DNS中设置A记录(对于BIND,请参见http://ma.tt/2003/10/wildcard-dns-and-sub-domains/)。在开发服务器上,通过将每个子域名添加到您的hosts文件中来伪造子域名会更好。

  2. (如果您使用了cPanel,则无需执行此操作)。您需要向apache vhosts文件添加以下内容。这在很大程度上取决于您运行的服务器类型(共享还是非共享)。以下代码不完整,仅供指导。注意:ServerAlias example.com *.example.com很重要。

    <VirtualHost 127.0.0.1:80>  
            DocumentRoot /var/www/  
            ServerName example.com  
            ServerAlias example.com *.example.com  
    </VirtualHost>
    
  3. 接下来,由于您可以使用PHP脚本检查“Host”标头并找出子域名并相应地提供内容。


0
我在Ubuntu 18.04上找到的解决方案类似于这个, 但涉及到NetworkManager配置:
  1. 编辑文件/etc/NetworkManager/NetworkManager.conf,并在[main]部分添加行dns=dnsmasq

    sudo editor /etc/NetworkManager/NetworkManager.conf
    

    应该看起来像这样:

    [main]
    plugins=ifupdown,keyfile
    dns=dnsmasq
    ...
    
  2. 开始使用NetworkManager的resolv.conf

    sudo rm /etc/resolv.conf
    sudo ln -s /var/run/NetworkManager/resolv.conf /etc/resolv.conf
    
  3. 创建一个带有通配符配置的文件

    echo 'address=/.localhost/127.0.0.1' | sudo tee /etc/NetworkManager/dnsmasq.d/localhost-wildcard.conf
    
  4. 重新加载NetworkManager配置

    sudo systemctl reload NetworkManager
    
  5. 测试一下

    dig localdomain.localhost
    

您还可以添加任何其他域名,这对于在本地开发环境中使用某些类型的身份验证非常有用。

echo 'address=/.local-dev.workdomain.com/127.0.0.1' | sudo tee /etc/NetworkManager/dnsmasq.d/workdomain-wildcard.conf

那么这就可以正常工作了:

dig petproject.local-dev.workdomain.com

;; ANSWER SECTION:
petproject.local-dev.workdomain.com. 0 IN   A   127.0.0.1

0
首先,我想允许用户发布页面并为每个页面提供自己选择的子域名(例如:user.mysite.com)。据我所知,最好的方法是使用 mod_rewrite 和 .htaccess 将 user.mysite.com 映射到 mysite.com/user,这样做正确吗?
你最好使用虚拟主机。这样,每个用户都可以拥有几乎独立于其他用户的 Web 服务器配置。
语法大致如下: DocumentRoot /var/www/user ServerName user.mysite.com ...

0

从我在许多网络主机上看到的情况来看,它们在apache上设置了虚拟主机。

因此,如果您的www.mysite.com是从/var/www提供服务的,您可以为每个用户创建一个文件夹。然后将虚拟主机映射到该文件夹。

有了这个,mysite.com/user和user.mysite.com都可以使用。

至于您的测试环境,如果您在Windows上,我建议您编辑HOSTS文件,将mysite.com映射到您的本地PC(127.0.0.1),以及您为测试设置的任何子域名。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接