package dnsfilter import ( "encoding/json" "net/http" "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/urlfilter/rules" ) var serviceRules map[string][]*rules.NetworkRule // service name -> filtering rules type svc struct { name string rules []string } // Keep in sync with: // client/src/helpers/constants.js // client/src/components/ui/Icons.js // Do not use ||example.TLD^ rule unless particular name is unique or many extensions belong to it var serviceRulesArray = []svc{ {"whatsapp", []string{"||whatsapp.TLD^"}}, {"facebook", []string{ "||facebook.TLD^", "||fbcdn.TLD^", "||accountkit.TLD^", "||fb.TLD^", "||fbsbx.TLD^", "||discoverapp.TLD^", "||freebasics.TLD^", "||freebasic.TLD^", "||internet.org^", "||messenger.TLD^", "||m.me^", "||i.org^", "||f8.TLD^", "||tfbnw.TLD^", "||fburl.TLD^", "||hob.bi^", "||workplace.TLD^", "||novi.TLD^", "||libra.org^", "||f8.TLD^", "||oculus.TLD^", "||acebook.TLD^", "||forecastapp.net^", "||adversarialnli.TLD^", "||facebookblueprint.TLD^", "||facebookrecruiting.TLD^", "||boostwithfacebook.TLD^", "||facebooksuppliers.TLD^", "||facebookbrand.TLD^", "||accessfacebookfromschool.TLD^", "||facebookcorewwwi.TLD^", }}, {"twitter", []string{"||twitter.TLD^", "||twttr.TLD^", "||t.co^", "||twimg.TLD^", "||ads-twitter.TLD^"}}, {"youtube", []string{ "||youtube.TLD^", "||ytimg.com^", "||youtu.TLD^", "||googlevideo.TLD^", "||youtubei.googleapis.TLD^", "||youtube-nocookie.TLD^", "||youtube", }}, {"twitch", []string{"||twitch.tv^", "||ttvnw.TLD^", "||jtvnw.TLD^", "||twitchcdn.TLD^"}}, {"netflix", []string{"||nflxext.TLD^", "||netflix.TLD^", "||nflximg.TLD^", "||nflxvideo.TLD^"}}, {"instagram", []string{"||instagram.TLD^", "||cdninstagram.TLD^", "||instagram-brand.TLD^"}}, {"snapchat", []string{ "||snapchat.TLD^", "||sc-cdn.TLD^", "||snap-dev.TLD^", "||snapkit.co", "||snapads.TLD^", "||impala-media-production.s3.amazonaws.TLD^", }}, {"discord", []string{"||discordapp.TLD^", "||discord.TLD^"}}, {"ok", []string{"||ok.ru^"}}, {"skype", []string{"||skype.TLD^", "||skypeassets.TLD^"}}, {"vk", []string{"||vk.TLD^", "||userapi.TLD^", "||vk-cdn.TLD^", "||vkuservideo.TLD^"}}, {"origin", []string{"||origin.com^", "||signin.ea.com^", "||accounts.ea.com^"}}, {"steam", []string{ "||steam.com^", "||steampowered.TLD^", "||steamcommunity.TLD^", "||steamstatic.TLD^", "||steamstore-a.akamaihd.net^", "||steamcdn-a.akamaihd.net^", }}, {"epic_games", []string{"||epicgames.TLD^", "||easyanticheat.TLD^", "||easy.ac^", "||eac-cdn.TLD^"}}, {"reddit", []string{"||reddit.TLD^", "||redditstatic.TLD^", "||redditmedia.TLD^", "||redd.it^"}}, {"mail_ru", []string{"||mail.ru^"}}, {"cloudflare", []string{ "||cloudflare.TLD^", "||cloudflare-dns.TLD^", "||cloudflareinsights.TLD^", "||cloudflarestream.TLD^", "||cloudflareresolve.TLD^", "||cloudflareclient.TLD^", "||cloudflare-quic.TLD^", "||cloudflareapi.TLD^", "||cloudflareapps.TLD^", "||cloudflarechallenge.TLD^", "||cloudflarepreview.TLD^", "||cloudflarepreviews.TLD^", "||cloudflarebolt.TLD^", "||cloudflare-free.TLD^", "||cloudflare-ipfs.TLD", "||cloudflareworkers.TLD^", "||cloudflarestatus.TLD^", "||cloudflareaccess.TLD^", "||cloudflareenterprise.TLD^", "||cloudflarespeedtest.TLD^", "||cloudflaressl.TLD^", "||encryptedsni.TLD^", "||mycloudflare.TLD^", "||workers.dev^", "||one.one^", "||warp.plus^", "||1.1.1.1^", "||dns4torpnlfs2ifuz2s2yf3fc7rdmsbhm6rw75euj35pac6ap25zgqad.TLD^", }}, {"amazon", []string{ "||amazon.TLD^", "||media-amazon.TLD^", "||primevideo.TLD^", "||amazontrust.TLD^", "||images-amazon.TLD^", "||amazonvideo.TLD^", "||assoc-amazon.TLD^", "||ssl-images-amazon.TLD^", "||amazonpay.TLD^", "||amazon-adsystem.TLD^", "||amazonaws.TLD^", "||aboutamazon.TLD^", "||awsdns-cn-00.TLD^", "||awsdns-00.TLD^", "||awsstatic.TLD^", "||comixology.TLD^", "||boxofficemojo.TLD^", "||aiv-delivery.TLD^", "||jtvnw.TLD^", "||awscloud.TLD^", "||goodreads.TLD^", "||shopbop.TLD^", "||fabric.TLD^", "||zappos.TLD^", "||6pm.TLD^", "||psdops.TLD^", "||woot.TLD^", "||mturk.TLD^", "||aiv-cdn.TLD^", "||a2z.TLD^", "||createspace.TLD^", "||aws", }}, {"ebay", []string{ "||ebay.TLD^", "||ebayimg.TLD^", "||ebaystatic.TLD^", "||ebaycdn.TLD^", "||appforebay.TLD^", "||ebayinc.TLD^", "||terapeak.TLD^", "||e-bay.TLD^", "||ebaydts.TLD^", "||shopping.TLD^", "||ebaystores.TLD^", "||ebayglobalshipping.TLD^", }}, {"tiktok", []string{ "||tiktok.TLD^", "||tiktokcdn.TLD^", "||musical.ly^", "||snssdk.TLD^", "||amemv.TLD^", "||toutiao.com^", "||ixigua.com^", "||pstatp.com^", "||ixiguavideo.TLD^", "||toutiaocloud.TLD^", "||bdurl.TLD^", "||byteimg.TLD^", "||muscdn.TLD^", "||bytedance.map.fastly.net^", "||douyin.TLD^", "||iesdouyin.TLD^", "||tiktokv.TLD^", }}, } // convert array to map func initBlockedServices() { serviceRules = make(map[string][]*rules.NetworkRule) for _, s := range serviceRulesArray { netRules := []*rules.NetworkRule{} for _, text := range s.rules { rule, err := rules.NewNetworkRule(text, 0) if err != nil { log.Error("rules.NewNetworkRule: %s rule: %s", err, text) continue } netRules = append(netRules, rule) } serviceRules[s.name] = netRules } } // BlockedSvcKnown - return TRUE if a blocked service name is known func BlockedSvcKnown(s string) bool { _, ok := serviceRules[s] return ok } // ApplyBlockedServices - set blocked services settings for this DNS request func (d *Dnsfilter) ApplyBlockedServices(setts *RequestFilteringSettings, list []string, global bool) { setts.ServicesRules = []ServiceEntry{} if global { d.confLock.RLock() defer d.confLock.RUnlock() list = d.Config.BlockedServices } for _, name := range list { rules, ok := serviceRules[name] if !ok { log.Error("unknown service name: %s", name) continue } s := ServiceEntry{} s.Name = name s.Rules = rules setts.ServicesRules = append(setts.ServicesRules, s) } } func (d *Dnsfilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Request) { d.confLock.RLock() list := d.Config.BlockedServices d.confLock.RUnlock() w.Header().Set("Content-Type", "application/json") err := json.NewEncoder(w).Encode(list) if err != nil { httpError(r, w, http.StatusInternalServerError, "json.Encode: %s", err) return } } func (d *Dnsfilter) handleBlockedServicesSet(w http.ResponseWriter, r *http.Request) { list := []string{} err := json.NewDecoder(r.Body).Decode(&list) if err != nil { httpError(r, w, http.StatusBadRequest, "json.Decode: %s", err) return } d.confLock.Lock() d.Config.BlockedServices = list d.confLock.Unlock() log.Debug("Updated blocked services list: %d", len(list)) d.ConfigModified() } // registerBlockedServicesHandlers - register HTTP handlers func (d *Dnsfilter) registerBlockedServicesHandlers() { d.Config.HTTPRegister("GET", "/control/blocked_services/list", d.handleBlockedServicesList) d.Config.HTTPRegister("POST", "/control/blocked_services/set", d.handleBlockedServicesSet) }