如何在PHP中启用用户自定义域名

6
我正在开发一个系统,用户可以在其个人资料中输入购买的域名,因此当访问他们的域名时,应替换为他们的自定义域名,例如

http://domain.com/custom-name 替换为 http://purchaseddomain.com

因此,当他们访问购买的域名时,它应将他们带到包括导航链接在内的个人资料页面,例如查看他们的记录将是:

http://domain.com/custom-name/records 替换为 http://purchaseddomain.com/records

Tumblr启用了此功能,但我不知道这是如何工作的:

enter image description here

这正是我喜欢此功能的方式,我在SO上搜索过,但似乎没有帮助。
现在的问题是,我不确定如何使用PHP验证、确认并将他们购买的域名合并到我的服务器中,而不会出现问题 - 我正在使用Codeigniter。
是否有一个稳定的插件/库或详细的教程,能够使自定义域掩盖内部域名?
我的服务器运行在Ubuntu 11.10上,使用nginx 1.0.6。
模板对我来说没问题,我可以做到 - 我需要帮助的只是如何安全地接受和合并他们的域名到我的服务器。

编辑:刚刚查看了nginx 虚拟主机示例,整体看起来不错,但是当域名有指向我的服务器的A记录时,我如何能动态添加/删除这些域名条目呢?


通常情况下,您会在使用模板设置时以编程方式生成URL,例如,您会使用<a href="{{ domain_url('foo') }}">而不是<a href="http://foo"> - Amber
这将高度取决于您的设置以及如何创建/设置他们的帐户,但dns_get_record()可能对您有用。 - animuson
在Apache上,您需要为该域创建一个虚拟主机,并指向./custom-name文件夹以及进行A记录检查(后端nslookup)。 - Lawrence Cherone
@LawrenceCherone,请仔细阅读我的问题,我没有使用Apache。 - MacMac
1
@lolwut 是的,我知道,但是对于nginx一定有类似的过程 http://wiki.nginx.org/VirtualHostExample - Lawrence Cherone
3个回答

3

您不需要将他们的域名合并到您的服务器上。

实际上,当他们注册域名后,他们会将其指向您的服务器。

在您的服务器配置中,您需要动态创建规则,隐式地将页面重定向到他们在您的服务器上创建的页面。

因此,用户将看到 http://purchaseddomain.com/on-uri,但您将提供页面 http://domain.com/custom-name/one-uri

即:

就像您在 .htaccess 中添加的那样 - 即使您不使用 Apache,这只是为了解释“系统”必须的:

RewriteCond %{HTTP_HOST} purchaseddomain\.com$ [NC]
RewriteRule (.*) /custom-name/$1

我没有使用Apache,我正在使用nginx,请看我的最近编辑。 - MacMac
4
我说过“就像”,我不能为你做这件事,我只是“指引你的方向”,你需要自己进行一些研究。尝试自己搜索如何动态定义RewriteRule。 - dievardump
也许你可以尝试阅读这篇文章:http://serverfault.com/questions/332804/nginx-dynamic-virtual-hosts - dievardump

0

被接受的答案提到了客户将他们的DNS指向您的Web服务器。但是,在当今这个时代,这还不足以使其正常工作。

如果您的客户只是将CNAME指向您的域或创建指向您的IP的A记录,并且您不处理这些自定义域的TLS终止,则您的应用程序将不支持HTTPS,没有它,您的应用程序将无法在这些自定义域上的现代浏览器中工作。

您需要在Web服务器前设置一个TLS终止反向代理。此代理可以在单独的机器上运行,但您也可以在与Web服务器相同的机器上运行它。

CNAME vs A记录

如果您的客户想要在其子域上使用您的应用程序,例如app.customer.com,则他们可以创建指向您的代理的CNAME app.customer.com

如果他们想要在其根域上使用您的应用程序,例如customer.com,那么他们将不得不在customer.com上创建指向您的代理IP的A记录。确保此IP永远不会更改!

如何处理TLS终止?

为了使TLS终止工作,您需要为这些自定义域发出TLS证书。您可以使用Let's Encrypt来完成。您的代理将看到传入请求的“Host”标头,例如“app.customer1.com”或“customer2.com”等,然后它将通过检查SNI来决定使用哪个TLS证书。
代理可以设置为自动为这些自定义域发出和更新证书。在新自定义域的第一个请求中,代理将看到它没有适当的证书。它将向Let's Encrypt请求新证书。Let's Encrypt将首先发出挑战以查看您是否管理该域,并且由于客户已经创建了指向您的代理的CNAME或A记录,这告诉Let's Encrypt您确实管理该域,并允许您为其发出证书。
为了自动发出和更新证书,我建议使用Caddyserver、greenlock.js、OpenResty(Nginx)。
简而言之,这里发生了什么; Caddyserver在443和80上监听,它接收请求,自动发出和更新证书,将流量代理到您的后端。
如何在我的后端处理它

您的代理正在终止TLS并将请求代理到后端。但是,您的后端不知道请求背后的原始客户是谁。这就是为什么您需要告诉代理在代理请求时包含其他标头以识别客户的原因。只需添加X-Serve-For: app.customer.comX-Serve-For: customer2.com或原始请求的Host标头。

现在,在后端接收代理请求时,您可以读取此自定义标头,并知道请求背后的客户是谁。您可以根据此实现逻辑,显示属于该客户的数据等。

更多信息

在代理池前面放置负载均衡器以提高可用性。您还必须使用分布式存储来存储证书和Let's Encrypt挑战。使用AWS ECS或EBS进行自动恢复,如果出现故障,否则,您可能会在半夜被唤醒,重新启动机器或手动重启代理。

如果您需要更多详细信息,可以在Twitter上私信我@dragocrnjac


-1

这是对我有用的代码:

server {
    server_name *.mydomain.com
    root        /var/www/$host;

    ...
}

然后,您需要创建类似于:/var/www/user1.mydomain.com/、/var/www/user2.mydomain.com/...的目录。

我无法想出如何将“.mydomain.com”从目录名称中删除。如果有任何想法,请告诉我:)


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