新闻详情

新闻详情

首页 / 资讯中心 / 详情

Nginx图片静态路由配置详解:location匹配与缓存防盗链实践

发布时间:2026/9/28 14:16:37来源:尧图网络
Nginx图片静态路由配置详解:location匹配与缓存防盗链实践
先说说我遇到的一个真实场景上个月同事把所有商品图片都塞进了Java应用里一台4核8G的机器Tomcat直接被图片流量打趴。当时临时加了一台nginx服务器就靠配置图片静态路由把压力全部扛住应用才缓过来。所谓图片静态路由本质就是让nginx收到类似/images/foo.jpg这种请求后直接到磁盘上把文件读出来返回给客户端整个过程不经过任何后端程序。这篇文章就把这件事掰开揉碎讲清楚你会看到location的匹配坑、root和alias的拼接差异、缓存与防盗链的完整配置以及上线后常见的排查方法。无论你是运维、后端还是学生都应该能照着落地。1. 先想清楚图片静态路由到底解决什么问题1.1 静态路由的定位nginx本身就是一个高性能的HTTP服务器和反向代理服务器。图片静态路由是指在nginx层面把请求URL映射到服务器上的真实文件路径然后直接响应文件内容。它和“反向代理到后端应用”有本质区别反向代理是把请求转发给Tomcat、Node或者某个API服务由程序动态生成内容而静态路由是直接读磁盘nginx内部通过sendfile等机制把文件内容发给客户端CPU和内存开销极低。这也是为什么静态资源密集的业务几乎都会用nginx而不用程序容器直接对外服务。图片请求和普通API请求不一样图片的特点是读多写少、文件数量大、单个体积通常不太大而且客户端需要长缓存来省流量。如果把图片请求发给Tomcat每张图都要走一遍线程池、Servlet、IO流几百个并发就能把应用线程池占满业务接口跟着变慢。nginx处理静态文件时传统模式是“一个进程/线程处理一个连接”但nginx用的是事件驱动模型配合sendfile把内核缓冲区的文件直接写给socket在静态文件场景里的并发能力远超一般应用服务器。所以第一步要建立的概念是图片路由不是简单写一行location而是要把nginx当作一个专门的静态资源网关来设计。1.2 图片业务场景下的特殊约束图片路由比CSS/JS这种静态资源路由更讲究因为图片几乎都是由客户端直接访问或经过CDN回源访问会有几个特殊约束。第一个是缓存策略。图片基本是不变的但很多团队因为没配对响应头导致浏览器每次刷新都重新下载。正确的做法是通过expires指令或Cache-Control头明确告诉浏览器“这张图片可以缓存30天”。而像HTML、JS这类文件缓存策略需要更谨慎图片则简单粗暴一点问题不大。第二个是访问控制。电商相册、私密分享这类场景图片不能裸奔全网访问至少要做referer防盗链防止别人把你的图片地址贴在自家网站上白白消耗带宽。更严格一点还要配合签名URL、token鉴权。第三个是高并发下的IO压力。图片量上来之后磁盘IO和文件句柄会成为瓶颈需要正确配置open_file_cache、sendfile等参数避免每次请求都对同一个文件做重复系统调用。你后面看我的完整配置会发现很多参数都是围绕这三个约束设计的。2. location是静态路由的命脉匹配规则与常见坑2.1 location匹配优先级一张表看懂写图片路由本质上是在写location。很多人配置不生效就是没搞懂nginx的location匹配顺序。nginx的location匹配规则有5种优先级从高到低如下写法含义优先级location /path精确匹配完全相等才命中最高location ^~ /path前缀匹配命中后不再检查正则高location ~ /path正则匹配区分大小写中location ~* /path正则匹配不区分大小写中location /path普通前缀匹配低这几种匹配同时存在时nginx先用普通前缀匹配记录最长的匹配项然后继续检查正则location。如果某个正则匹配成功普通前缀匹配作废除非普通前缀前有^~修饰符才会在匹配后直接跳过正则。还有一个精确匹配只要命中就直接结束不再检查任何规则。举个我们常见的例子如果同时配置了location /images/和location ~* \.(jpg|png)$用户访问/images/cat.jpg时虽然/images/前缀匹配上了但因为后面有正则匹配了.jpg所以实际生效的是正则location而不是前缀location。这个坑特别隐蔽很多人以为自己配的alias没生效其实是因为请求被后面的正则规则抢走了。2.2 root和alias路径拼接的两种算法图片路由里另一个绕不开的概念就是root和alias。这两个指令都是用来指定文件路径的但拼接逻辑完全不同。搞清楚这一点80%的路径错误都能避免。root的拼接规则是root路径 完整请求URI。举个例子location /images/ { root /data/www; }请求/images/cat.png时nginx会找/data/www/images/cat.png这个文件。注意/data/www后面会直接接上完整的URI也就是/images/cat.png所以最终路径里会出现一个images目录。很多新手以为root指向的是图片目录就直接配root /data/images;结果实际找的是/data/images/images/cat.png不404才怪。alias的拼接规则是alias路径 去除location前缀后的URI。比如location /images/ { alias /data/images/; }请求/images/cat.png时nginx先去掉location前缀/images/剩下来cat.png然后拼接到alias路径上最终找/data/images/cat.png。这样反而更符合直觉“images”这个URL前缀和磁盘目录名并不强制一致。这里有个细节必须注意如果location以/images/这种斜杠结尾alias路径也最好以斜杠结尾。如果location /images/配合alias /data/images没有结尾斜杠访问/images/cat.png时实际会找/data/imagescat.png路径直接被拼接错了。反过来如果location /images不带斜杠配合alias /data/images/访问/images/cat.png时nginx去掉前缀时会继续处理斜杠最终变成/data/images//cat.png虽然Linux里双斜杠通常能访问但总归不是规范路径。所以我习惯的做法是location和alias都统一带尾斜杠避免各种边缘情况。2.3 选型建议什么时候用root什么时候用alias我的经验是如果静态资源的URL前缀和磁盘目录名一一对应那用root更省事。比如图片统一放在/data/www/images/下URL是/images/xxx.jpg直接用root /data/www;不需要额外对齐配合^~前缀就可以稳定工作。但当URL前缀和磁盘目录名不一致时alias更方便。比如URL设计成/pic/xxx.jpg但文件实际存储在/data/photos/xxx.jpg这时候alias可以避免在磁盘上再建一层pic目录。又比如用nginx做下载站URL是/download/但文件分布在多个磁盘目录用alias一个个映射很清晰。另外正则location里不能用alias这时候只能用root。为什么因为alias在正则匹配时无法确定该截掉多少URL前缀所以nginx直接用root来拼接。如果你在正则location里写了aliasnginx启动时甚至直接报错。这个限制是我刚学nginx时踩过的坑当时正则location里写了aliasnginx -t直接提示“alias cannot be used in regex location”。多理解这个限制就能少做很多无用功。3. 可直接抄的完整配置从单目录到多场景3.1 最简配置一个location搞定图片目录先给一套最基础的图片静态路由配置适合小项目、个人网站或临时使用。假设图片存放在/data/www/images你想要用http://your-server/images/xxx.jpg访问到它。server { listen 80; server_name img.example.com; location ^~ /images/ { root /data/www; expires 30d; access_log off; } }这里用了^~修饰符意思是只要URL以/images/开头就直接使用这条规则不再检查后面的任何正则匹配。这样能避免前面说的“正则location抢走图片请求”的问题。root /data/www;配合location /images/的拼接结果是/data/www/images/xxx.jpg正好对应我们预先放置的目录。expires 30d会返回Cache-Control: max-age2592000和Expires头让浏览器强缓存30天。图片访问量一大日志会刷得飞快所以我直接access_log off减少很多磁盘IO。如果你的nginx用户比如nginx或www-data对文件目录没有读权限启动后访问会出现403或者日志里看到Permission denied。所以确认目录权限时可以执行ls -ld /data/www/images确保nginx运行用户对该目录有r-x权限对文件有r权限。如果用的是阿里云或腾讯云默认环境还要注意Linux的SELinux是否拦截可以先setsebool -P httpd_read_user_content 1临时验证确认是SELinux问题再调整。3.2 增强版缓存、防盗链、默认图一站配齐真实项目不会只有一块图片目录可能还要处理缩略图、默认图、防盗链、来源统计等。下面这套是我在生产环境里常用的一版可以直接复制改改路径就能用。server { listen 80; server_name img.example.com; root /data/www; access_log /var/log/nginx/img.access.log combined; # 静态图片统一匹配常见图片扩展名 location ~* \.(gif|jpg|jpeg|png|webp|bmp|ico)$ { root /data/www/images; expires 30d; add_header Cache-Control public, image-max-age2592000; try_files $uri /images/default.jpg; access_log off; } # 明确的前缀目录防止被正则覆盖 location ^~ /avatar/ { alias /data/www/avatar/; expires 7d; valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 403; } } # 隐藏/忽略favicon日志 location /favicon.ico { log_not_found off; access_log off; } # 禁止目录浏览 location ~ ^/images/.*\.(?:php|sh|txt)$ { deny all; return 404; } }这里几个点值得详细说明。第一正则location匹配图片扩展名但root指向/data/www/images所以请求/img.jpg时实际路径是/data/www/images/img.jpg不推荐再带上完整的/images前缀URL否则会路径重复。try_files的作用是当文件不存在时回退到/images/default.jpg这样用户那张破图虽然没找到但不至于饿死适合素材库场景。如果你有多个目录可以把try_files $uri /images/default.jpg;改成回退到CDN或者400。第二valid_referers和if ($invalid_referer)用来做基础防盗链。none表示允许没有Referer的请求比如直接输入图片URLblocked表示允许某些被代理服务隐藏了Referer的情况server_names表示允许本站域名和*.example.com。只要Referer不是这些列表里的就会返回403。注意if在nginx里属于“邪恶指令”使用场景越少越好但防盗链的valid_referers结合if是官方比较经典的用法放在这里问题不大。真正严格的企业场景一般会在代码层生成签名URL比如加上时间戳和md5nginx用secure_link模块校验这个下文再扩展。第三最后那个正则匹配\.(php|sh|txt)$是为了防止有人往图片目录里上传webshell或者侦察文件虽然nginx本身不会执行php但直接返回404更安全。3.3 动静分离场景中的图片路由与后端合作静态路由不一定要让图片只存在nginx本地磁盘有时候图片在另一台文件服务器上或者后端应用会动态生成缩略图。这时nginx就需要结合反向代理做动静分离。所谓动静分离就是静态资源请求走nginx静态路由动态请求走后端服务。我用过一个比较典型的配置server { listen 80; server_name www.example.com; root /data/www; # 静态图片 location ^~ /static/ { alias /data/www/static/; expires 30d; } # 动态接口 location /api/ { proxy_pass http://backend_upstream; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 后端动态图片生成接口比如缩略图 location ~ ^/thumbs/(.*)$ { proxy_pass http://backend_upstream/resize/$1$is_args$args; proxy_cache thumb_cache; proxy_cache_valid 200 1h; } }动态接口这里容易踩坑。proxy_pass http://backend_upstream;不带路径时nginx会把完整URI传给后端但如果proxy_pass后面带了路径比如/resize/nginx会用location匹配后的剩余部分去替换。我在正则location里写了proxy_pass http://backend_upstream/resize/$1$is_args$args;$1就是正则匹配的括号内容这样就实现了/thumbs/abc.jpg转成后端/resize/abc.jpg。同时给缩略图接口挂了proxy_cache缓存在nginx层后端的图片生成压力会小很多。不过要注意如果后端返回的图片带有Set-Cookie或动态参数最好别缓存否则可能把别人的私有图片缓存给其他用户。这里我只缓存了HTTP 200响应且有效期1小时再用proxy_cache_key加上URI和args。4. 上线后必查性能与安全问题排查4.1 权限导致的403/404图片路由上线后最容易碰到的就是403和404混着来。403一般不是路径写错了而是权限或者SELinux的问题。nginx进程运行用户默认是nginx它要读取/data/www/images下的文件就必须有目录的读和执行权限。目录没有x权限时即使文件有r权限也读不了。你可以一步步排查ls -ld /data/www /data/www/images ps aux | grep nginx namei -om /data/www/images/cat.pngnamei命令会逐层检查路径上每一层的权限非常直观。如果是权限不够直接chmod -R 755 /data/www配合chown -R nginx:nginx /data/www。但注意不要随便用777和公网服务器上开放目录没什么区别。如果权限没问题但nginx日志里仍然有Permission denied那多半是SELinux的锅报错里会出现“Permission denied”却看不到权限问题此时可以getenforce看状态临时用setenforce 0验证。SELinux的httpd_t类型默认只允许读/var/www/html你的自定义目录/data/www不在白名单里就需要chcon -R -t httpd_sys_content_t /data/www或改布尔值。404就比较直接了优先看nginx -T输出的实际配置确认当前生效的location是哪个然后用curl -I http://localhost/images/cat.png观察响应头。如果返回404把nginx配置里的root/alias路径拿到命令行ls -l看文件是否存在。别忽略文件名大小写问题Linux是区分大小写的Cat.png和cat.png是不同文件。正则匹配~区分大小写~*不区分用错也会导致某些图片404。4.2 缓存不生效的三种原因图片强缓存不生效最常见的是三种一是响应头没有Cache-Control或Expires二是同时加了expires和add_header Cache-Control导致后者覆盖了前者三是URL不变但文件内容变了浏览器直接走协商缓存。我遇到过一个很蠢的配置在同一location里先写expires 30d;又写add_header Cache-Control no-store;结果后面的add_header会覆盖掉expires生成的Cache-Control头浏览器每次都要回源。所以在配置里如果你要用add_header Cache-Control public, max-age2592000;就别再加expires了或者只留其中一个。这里推荐直接使用expires 30d;nginx会自动生成带max-age的Cache-Control除非你要定制public, immutable这类特殊指令才需要add_header。另一个问题是浏览器缓存明明设置了max-age2592000但刷新后仍然发起请求。这种情况一般是URL没变图片本身被强制刷新或者浏览器策略里勾了“禁用缓存”。强缓存生效期间浏览器根本不会发出请求通过开发者工具看到的是from disk cache或from memory cache这才是真正命中强缓存。如果看到网络请求有304那是协商缓存不是强缓存。图片这种资源要减少回源可以给图片加上版本参数或者文件名带哈希比如/images/cat_v1.jpg新版本就换一个URL不然即使缓存过期后用户也能收到旧图。4.3 性能调优参数清单图片并发量上来之后nginx有几个参数非常值得调。完整版放在http块里不一定每个项目都要全开我通常按需调整http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 30; open_file_cache max10000 inactive60s; open_file_cache_valid 120s; open_file_cache_min_uses 2; open_file_cache_errors on; gzip on; gzip_types text/plain text/css application/json image/svgxml; gzip_disable msie6; }sendfile on的作用是让nginx直接从内核缓冲区复制文件到socket减少用户态和内核态的数据拷贝次数这是nginx处理静态文件性能高的关键。配合tcp_nopush on在sendfile模式下会尽量把多个数据包合并发送提高网络利用率。tcp_nodelay则在keepalive连接上关闭Nagle算法降低小文件的延迟。open_file_cache用于缓存文件描述符、文件大小和修改时间这对图片这种反复访问的静态资源特别有效。参数含义是最多缓存10000个文件句柄60秒内没有访问就淘汰每120秒检查一次缓存里的文件是否过期一个文件被访问至少2次才放入缓存。有了它nginx每次访问图片不像原来那样都去操作系统拿文件元数据而是直接在缓存里读取文件打开的系统调用会大幅减少高并发时明显更稳。对于图片本身我没开gzip因为jpg/png/webp本身就是压缩过的再压缩只会浪费CPU。但如果你有SVG或者纯文本的JSON接口可以按上面的gzip_types开一下。另外如果图片放在机械磁盘上还可以考虑directio 4m大文件绕过分页缓存直接DMA读取但一般图片服务用SSD就没必要了。4.4 安全加固防盗链、目录保护与跨域图片路由的安全不只是权限和SELinux。至少还要做三件事目录不可列举、防止路径穿越、保护图片不被盗链。目录不可列举很简单只要你的location里没有autoindex on;nginx默认就不会显示目录列表。这个指令千万不能随手开我在测试机上出现过location / { autoindex on; }结果整个磁盘目录全暴露了。真需要临时共享文件也应该单独用一个子location并加上IP白名单。路径穿越问题是nginx和Web应用的老话题。使用alias时尤其要小心因为alias是“去掉一段前缀再拼接路径”如果配置不当用户可能通过/images/../secret.txt之类的URL访问到目录外的文件。不过新版nginx对normalized URI本身会做.啊..的解析请求到location匹配前已经被规范化了所以直接/../是过不去的。但如果你用正则location再去拼接$1比如proxy_pass就要特别小心最好对捕获的路径做一次校验防止把../再塞进上游。真正被攻击的案例很多都是因为用了uri变量时忘了它会包含未解码的原始请求。这里我倾向于一个原则凡是图片路由后面需要连接文件系统的都不要用$uri字符串自己拼路径而是用alias或root让nginx自己处理。防盗链上节已经给过配置这里补充一个更简单也常用的做法。如果你不关心Referer细节直接拒绝非本站或者空Referer以外的请求可以写location ~* \.(gif|jpg|jpeg|png|webp)$ { valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 403; } expires 30d; }none和blocked都放行是因为防盗链不能太狠否则用户直接打开图片地址会被误杀。如果你连空Referer也要禁掉可以把none去掉但图片分享后可能没法直接看。更严谨的做法是使用secure_link模块在URL里带一个过期签名比如/images/abc.jpg?stxxxxe时间戳nginx校验签名合法且未过期才放行CDN回源时也可以用这个机制。这个模块需要编译nginx时加--with-http_secure_link_module不少发行版默认没带。还有一个容易被忽视的跨域问题。如果你前端在www.example.com图片放在img.example.com浏览器加载图片默认是不会拦截img标签的但在Canvas绘图或fetch请求场景下会触发跨域。所以我通常在图片location里加一行add_header Access-Control-Allow-Origin *;图片本身是公开资源开这个风险不大。如果图片涉及用户隐私那就别开了。5. 我踩过的坑和最后的小技巧5.1 几个真实事故复盘第一个事故配置了location /images/和location ~* \.(png|jpg)$结果所有图片请求都走了正则locationalias没生效图片404。排查了半小时最后用nginx -T看实际生效的location才发现问题。解决办法是把图片目录location改写成location ^~ /images/这样前缀匹配优先级高于正则彻底规避了匹配顺序的坑。第二个事故所有图片返回403明明文件权限是755。折腾半天才发现是SELinux拦截了/data/images目录因为不是标准的/var/www/html路径。当时的处理是用chcon -R -t httpd_sys_content_t /data/images给目录打上SELinux标签以后再也不误伤。如果你不想用SELinux也可以考虑直接在nginx的systemd单元文件里加PrivateDevices之类的沙箱隔离但一般业务环境我建议保留SELinux并正确打标签。第三个事故给图片配置了expires 30d;但前端朋友说图片改了以后还是旧图。原因就是文件名没变浏览器强缓存了30天。后来我们改成文件名带版本号或内容哈希新图片用新URL旧URL自然缓存期结束就没人访问了。不要为了省事不换URL否则清缓存是个大麻烦。5.2 几个不常被提到的小技巧图片路由里有三个小技巧值得分享。第一在测试配置时一定要用nginx -t检查语法然后再nginx -s reload生产环境千万别直接重启不然连接会瞬断。我自己习惯在部署脚本里先cp nginx.conf nginx.conf.bak确认没问题后再reload回滚也方便。第二如果你用的是云厂商的负载均衡或CDN注意回源请求的Host头和X-Forwarded-For。图片静态路由的日志最好单独记录真实客户端IP否则你在nginx里看到的全是一堆CDN节点IP排查问题会非常痛苦。配置里可以加上real_ip_header X-Forwarded-For; set_real_ip_from 0.0.0.0/0;让nginx直接信任CDN传来的客户端IP。第三图片目录里可以放一个robots.txt但不是所有静态资源都需要被搜索引擎收录。如果图片是给登录用户看的私密内容建议在根location加add_header X-Robots-Tag noindex, nofollow;防止被搜索引擎索引。虽然这不是nginx的“路由”功能但对图片服务来说是很好的补充。最后再聊一个小细节配置里我反复强调^~是因为图片路由经常和正则location打架。如果你以后在配置里看到图片路径明明写对了但实际访问总是走另一个规则优先怀疑是不是正则location抢了优先级。用curl -I和nginx -T对比比盯着配置文件猜快得多。静态路由本身不复杂复杂的是它和匹配规则、缓存、权限、安全这些边界问题纠缠在一起。把这几个交叉点都理清图片服务就算再压几倍流量nginx也能稳稳接住。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Codex写运维脚本能提效88%,但在生产跑之前你得先回答一个问题:dry-run 与提示词边界怎么定 2026/9/28 18:23:44

Codex写运维脚本能提效88%,但在生产跑之前你得先回答一个问题:dry-run 与提示词边界怎么定

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Catch2 发布流程全解析:语义版本递增、自动化发布脚本与 PGP 签名(TEN-framework 仓库内 Catch2 发布指南详解) 2026/9/28 18:23:44

Catch2 发布流程全解析:语义版本递增、自动化发布脚本与 PGP 签名(TEN-framework 仓库内 Catch2 发布指南详解)

人工智能AI Agent多模态语音AI 应用 【免费下载链接】ten-framework Open-source framework for conversational voice AI agents 项目地址: https://gitcode.com/TEN-framework/ten-framework 点击查看 免费下载 导读 本文基于 TEN-framework 仓库内随源码一同 v…

阅读更多 →
AI 编程 Agent 删库事故复盘:Claude 4.6 权限失控,用 TaoToken 统一 Key 给 Cursor 加一道配置防线 2026/9/28 18:23:44

AI 编程 Agent 删库事故复盘:Claude 4.6 权限失控,用 TaoToken 统一 Key 给 Cursor 加一道配置防线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
大模型应用开发指南:从模型选型到本地部署与微调实践 2026/9/28 18:23:44

大模型应用开发指南:从模型选型到本地部署与微调实践

这两年,大模型(LLM)这三个字几乎把互联网的每一个角落都塞满了,但一个很有意思的现象是:真正把大模型用起来的人,和围观热闹的人,中间往往隔的不是技术深度,而是信息整理门槛。模型名…

阅读更多 →
Claude Code 重构 Vue2 老项目到 Vue3 + TS:TaoToken 配置与迁移验证指南 2026/9/28 18:23:43

Claude Code 重构 Vue2 老项目到 Vue3 + TS:TaoToken 配置与迁移验证指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
200万字无损上下文怎么接?Kimi智能助手配 TaoToken 的 config.toml 骨架与验证 2026/9/28 18:23:31

200万字无损上下文怎么接?Kimi智能助手配 TaoToken 的 config.toml 骨架与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉