<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/feed.css"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Sean Wei</title>
    <description>資安、網路治理，以及那些我追下去的事</description>
    <link>https://blog.sean.taipei/</link>
    <atom:link href="https://blog.sean.taipei/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 31 Aug 2026 12:16:19 +0000</pubDate>
    <lastBuildDate>Mon, 31 Aug 2026 12:16:19 +0000</lastBuildDate>
    <generator>Astro</generator>
    <item>
      <title>A fake parcel site, and the six buttons that run it</title>
      <pubDate>Tue, 18 Aug 2026 08:10:00 +0000</pubDate>
      <description>A fake Colombian postal site asks for a small customs fee. The moment you enter your card, a person on the other end starts deciding, in real time, what to make you hand over next. This is that machine taken apart, along with the console it left in plain sight.</description>
      <link>https://blog.sean.taipei/2026/08/parcel-phishing-en</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2026/08/parcel-phishing-en</guid>
      <content:encoded>&lt;p&gt;&amp;quot;Your package is being held at customs. Pay a small duty to release it.&amp;quot; You probably get a few of these in any given month. This post takes apart one version of the trick, aimed at Colombians and impersonating the country's national postal service, 4-72. Most phishing sites you actually run into are crude, and the ones imitating a government service are usually the crudest of all. This one is not. And the trouble starts after you enter your card: there is not just an automated script at the other end, there is a live person waiting.&lt;/p&gt;
&lt;p&gt;On the evening of Saturday 15 August (UTC), someone used my URL shortener &lt;a href=&quot;https://tg.pe/&quot;&gt;tg.pe&lt;/a&gt; on a link. Anyone can, without an account. The destination was &lt;code&gt;paquetes-colombia.blog&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There is also a &lt;a href=&quot;https://blog.sean.taipei/2026/08/parcel-phishing-zh&quot;&gt;Mandarin version&lt;/a&gt; of this post. 台灣朋友歡迎左轉 &lt;a href=&quot;https://blog.sean.taipei/2026/08/parcel-phishing-zh&quot;&gt;中文版&lt;/a&gt;。&lt;/p&gt;
&lt;h1&gt;A brand-new domain dressed as a government site&lt;/h1&gt;
&lt;p&gt;First, consider how new it was. RDAP, the public record of who registered a domain and when, puts registration at 16:59 UTC on 15 August, and the link reached tg.pe three hours later. tg.pe puts links to a domain this new into a honeypot by default: the submitter is told it worked, the link does redirect normally for a short window, and then it self-destructs within minutes and returns nothing but 404s. I covered the logic of distrusting new domains in the &lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-en&quot;&gt;previous post&lt;/a&gt;, and will not repeat it here.&lt;/p&gt;
&lt;p&gt;Sweeping my own doorstep is the bare minimum. The domain was still live, and copies of the link would keep spreading by SMS and email, so I did what I always do and opened it by hand. What I found was much more elaborate than the one-page fake login from last time.&lt;/p&gt;
&lt;p&gt;It is a whole kit, impersonating 4-72 down to the layout and the fonts: the banner of GOV.CO, Colombia's government web portal, runs across the top, and the footer copies 4-72's tax number. The laziest part is the images: the favicon (the little browser-tab icon) and the GOV.CO banner graphic are both hotlinked straight from 4-72's own servers. That shortcut has a price. The hostname of every front in this campaign is sitting in 4-72's own access logs, with a referrer, in near real time. The impersonated brand is holding a ready-made list of the sites impersonating it, and almost nobody monitors for it.&lt;/p&gt;
&lt;p&gt;The whole thing sits behind Cloudflare, acting as a reverse proxy in front of the real server, and the protection level was turned up far enough to throw a challenge page. That was a setting the operators switched on in their own Cloudflare account, and the effect was that every scanner judging the page by fetching it got nothing but &amp;quot;prove you are not a robot&amp;quot;. urlscan's score for the domain came back 0. But &amp;quot;they were all blinded&amp;quot; would not be accurate: urlscan's own machine-learning engine still called it malicious, at 96, and by the time the link reached tg.pe VirusTotal had one engine calling it malicious and one calling it suspicious. Those verdicts cannot have come from the page, because the wall was in the way. What they were reading instead, the vendors do not say.&lt;/p&gt;
&lt;h1&gt;The six-dollar calculation&lt;/h1&gt;
&lt;p&gt;Whatever tracking number you type, as long as it is long enough to pass, the page comes back with the same line: your package is &amp;quot;Retenido en aduana&amp;quot; (held at customs), and a duty is owed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-customs.png&quot; alt=&quot;The fake customs page&quot;&gt;
&lt;em&gt;The fake customs page: the amount is only 19,900 pesos, and the demand is dressed up with Colombia's real customs statute, plus a fake resolution from DIAN, the country's tax and customs authority, for weight.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;19,900 Colombian pesos is about six US dollars: small enough that you would not stop to call the post office, and squarely in the range where people think &amp;quot;fine, I'll just pay it&amp;quot;. Add a real statute and a real government agency and it feels thoroughly official. But the six dollars is only the entry fee. The next page is what they are after.&lt;/p&gt;
&lt;h1&gt;A payment form that asks for orders every three seconds&lt;/h1&gt;
&lt;p&gt;Press &amp;quot;pay&amp;quot; and a form appears: cardholder name, card number, expiry, CVV (the code on the back of the card).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-card.png&quot; alt=&quot;The fake payment page&quot;&gt;
&lt;em&gt;The catch is here: full card details, all at once.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So far, nothing unusual. What is strange is what happens behind it. From the moment you open this page, it asks its own server every three seconds, &amp;quot;Where do I send this person next?&amp;quot; It is waiting for a person to tell it what to do.&lt;/p&gt;
&lt;p&gt;That is because the card number you just entered is going straight into a Telegram group, and the message the criminals receive comes with a row of buttons under it.&lt;/p&gt;
&lt;h1&gt;The six buttons on the operator's phone&lt;/h1&gt;
&lt;p&gt;In the seconds you spend hesitating on the payment page, a phone buzzes somewhere far away: your card number appears with six buttons beneath it, and someone is choosing what to ask you for next. Like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-panel.png&quot; alt=&quot;What the operator sees (reconstruction)&quot;&gt;
&lt;em&gt;The operator's side of the screen, with the six buttons: OTP (a one-time code) by SMS, OTP by email, 3-D Secure, PIN, invalid card, finish. This is a reconstruction I built with my own bot and placeholder data, not a captured screen.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I am not guessing at those six buttons. The site leaves its own source in plain view, in the payment page's front-end JavaScript, which spells out exactly which buttons go into the Telegram message. Transcribed from the copy I took while the site was still up:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const keyboard = [
  [btn('📲 OTP SMS', 'redirect_sms'),  btn('📧 OTP Email', 'redirect_email')],
  [btn('🔒 3D Secure', 'redirect_vbv'), btn('🔢 PIN', 'redirect_pin')],
  [btn('❌ Tarjeta inválida','invalid_card'), btn('🏁 Finalizar','redirect_success')]
];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each button points to &lt;code&gt;cmd.php?uid=&amp;lt;victim-id&amp;gt;&amp;amp;cmd=&amp;lt;action&amp;gt;&lt;/code&gt;. These are Telegram URL buttons, not callback buttons, so pressing one opens &lt;code&gt;cmd.php&lt;/code&gt; in the operator's own browser. Every command they issue is a request from their own address, landing in that server's access log. None of that is visible from outside; only whoever runs that server can see it.&lt;/p&gt;
&lt;p&gt;Whichever button the operator presses, your browser jumps to the matching screen within three seconds.&lt;/p&gt;
&lt;p&gt;Getting the screenshots below required no card: where those commands send a victim is written in that same block of JavaScript (only &amp;quot;invalid card&amp;quot; stays put and just shows an error), so requesting those URLs directly is enough to see the pages.&lt;/p&gt;
&lt;p&gt;They press &amp;quot;OTP SMS&amp;quot;, and your screen shows a field waiting for the code your phone just received.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-otp.png&quot; alt=&quot;The fake SMS verification page&quot;&gt;
&lt;em&gt;What the victim sees: a field waiting for the SMS code. The operator only has to press a button.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A press of &amp;quot;invalid card&amp;quot; tells you the number was wrong and asks you to type it again. Nastier is &amp;quot;3-D Secure&amp;quot;, the extra confirmation your bank runs on an online card payment: the screen tells you to confirm the transaction in your banking app. Nothing is stolen on this screen. Its purpose is to push you into your own bank's app to approve the charge the operator is submitting at that moment, while you believe you are approving the customs fee.&lt;/p&gt;
&lt;p&gt;All of it is built for one thing: they charge your card while lifting each of the bank's confirmations off you in real time. None of the bank's checks are broken or removed. Every one of them runs, and every one of them passes, because the cardholder is on the line supplying the answer at the exact moment it is asked for. The SMS code and 3-D Secure are designed for a thief who cannot reach you while the bank is asking. This kit's whole job is to be reaching you at that moment.&lt;/p&gt;
&lt;h1&gt;Who is pressing the buttons&lt;/h1&gt;
&lt;p&gt;The Telegram bot's credential (its bot token, effectively its username and password) is written into the page source in plain sight (&lt;code&gt;7362…&lt;/code&gt;). It did not have to be: the site already has an &lt;code&gt;api.php&lt;/code&gt; of its own taking the card details, so the send to Telegram could have happened there, on the server, with the token never leaving it. It is in your browser purely because the developer could not be bothered.&lt;/p&gt;
&lt;p&gt;Anyone who can read the source can use it to ask the bot who it has been talking to, and I did. I used &lt;code&gt;getMe&lt;/code&gt; and &lt;code&gt;getUpdates&lt;/code&gt;, the calls that read without disturbing anything. Beyond that I issued no commands, never touched &lt;code&gt;cmd.php&lt;/code&gt; (which drives a victim's browser), and never submitted anything to the kit's forms. I would rather not dress that up as &amp;quot;read-only&amp;quot; and leave it there: it is still authenticating to a third-party service with someone else's credential, and whether that holds up depends on where you are. If you find a credential in someone else's page source, the right move is to report it, not to log in.&lt;/p&gt;
&lt;p&gt;The bot is called &amp;quot;KING DE L'ATLAS&amp;quot;, French for King of the Atlas. It belongs to two Telegram groups: one called &amp;quot;4-72 #1&amp;quot;, which gets the live &amp;quot;someone has just opened the site&amp;quot; pings; and one called &amp;quot;COLOMBIE&amp;quot; (French for Colombia), where the stolen cards are posted.&lt;/p&gt;
&lt;p&gt;The stolen cards are posted straight into the group, but Telegram does not hand a bot's own outgoing messages back to me. I could only see the ones an operator had quoted in a reply: six complete cards, plus one SMS code caught live. I will not reproduce them. At least six, then, with no way to infer how many people were taken in total.&lt;/p&gt;
&lt;p&gt;Those six cards all satisfy the Luhn checksum that card numbers carry, and their leading digits fall in ranges issued by Colombian banks. I passed the card data separately, encrypted, to colCERT, Colombia's national computer emergency response team, so they can route it to the issuers and the cardholders can be warned. Only an issuing bank can freeze a card or reverse a charge. That was never mine to do.&lt;/p&gt;
&lt;p&gt;From the messages, at least two accounts were talking in the group, in French, and one of those account names is a word from Maghrebi Arabic. The bot is named after the Atlas, the mountain range that runs across North Africa. Together those point at a French-speaking Maghrebi context, and no further: they are clues from naming and language, not a nationality or a location. The kit's own code comments are in French too, which matches the group, so in this case the people who built the tool and the people pressing the buttons look like the same group.&lt;/p&gt;
&lt;p&gt;Their handles, their messages, the way they address each other: all of it was visible while I was checking, and none of it is in this post. I will name infrastructure; I will not name accounts that map to people. Partly because seeing is not proving, and if one of those accounts was itself stolen, the person named is not the person responsible. And partly because what this post is examining is the mechanism, and posting handles would only pull the focus onto catching people.&lt;/p&gt;
&lt;h1&gt;This is only #1&lt;/h1&gt;
&lt;p&gt;That group's name, &amp;quot;4-72 #1&amp;quot;, has a number in it. People rarely number the only thing they have.&lt;/p&gt;
&lt;p&gt;I pulled on that thread, and &lt;code&gt;paquetes-colombia.blog&lt;/code&gt; turned out not to be the only one. A domain registered back in July, &lt;code&gt;envio-colombia.blog&lt;/code&gt;, runs the same kit down to &lt;code&gt;CO587294163&lt;/code&gt;, the fake tracking number pre-filled on the lookup page.&lt;/p&gt;
&lt;p&gt;More than that: I fingerprinted it directly. It sends the cards it steals to the same Telegram bot and the same group. As each card goes out, the kit takes its first six digits to a third-party service to look up the issuing bank and the card type, and attaches that to the operators' message. Both sites use the same key for it. So these two sites do not just share a kit, they share a back end: the front changes names, and the cards land in the same group.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;envio-colombia.blog&lt;/code&gt; was still up at 09:36 UTC on Tuesday 18 August, still sitting behind the same challenge wall, its card page still being served. It went out in the same reports as paquetes: the registry and the registrar got it in the Sunday morning follow-up (the first report named only paquetes; I added the rest of the cluster ninety minutes later), and Cloudflare, the browser blocklists and the threat-sharing platforms followed on the 17th.&lt;/p&gt;
&lt;h1&gt;What I did&lt;/h1&gt;
&lt;p&gt;Once the link itself had been dealt with automatically, I wrote the case up and sent the report in three directions. Over the two days that followed, the fastest response came from the middle of the stack. The naming layer, the one that should act, took the long way round, and what moved it was not the door I knocked on first. The layer that could cut the whole operation in one go has not moved at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To make it findable.&lt;/strong&gt; Two threat-sharing platforms: the MISP community operated by CIRCL (Luxembourg's computer emergency response team), and abuse.ch's ThreatFox. This does not make a site disappear. It means the next person who runs into the same infrastructure can look it up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To make it stop.&lt;/strong&gt; Every upstream layer that can act: Cloudflare, the registrar that sold the domain (NameSilo), the registry that runs all of .blog, the hosting provider whose machine the files actually sit on, and Telegram, whose bot the operators run this on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To warn the people affected.&lt;/strong&gt; The impersonated 4-72, and Colombia's national CERT, colCERT. Those six card records went out along this path, encrypted, so the issuers can be told and the cardholders warned.&lt;/p&gt;
&lt;p&gt;The Telegram cut is worth being precise about. Stopping the bot would not stop this site collecting cards, because the card already goes into the kit's own &lt;code&gt;api.php&lt;/code&gt; on the same server. What it would break is the live relay: without the notification that a card has landed, the operator cannot press any of those six buttons. And because the two fronts I fingerprinted share one bot, that single cut lands on more than one site.&lt;/p&gt;
&lt;p&gt;The bot credential, both group IDs and both operator accounts went to Telegram at 01:11 UTC on Sunday. Fifty-six hours later, on Tuesday evening, the bot was still live and neither the groups nor the accounts had been touched. This was the one cut that would have broken the relay on both sites at once. Telegram has not replied.&lt;/p&gt;
&lt;p&gt;Cloudflare was the quickest. I filed at 01:00 UTC on Sunday, and the interstitial was up before 04:00: the lower bound is the last time I saw the domain unactioned, 03:06, and the upper bound is Cloudflare's own reply saying it had acted, 03:24. But a &amp;quot;Suspected Phishing&amp;quot; page is a warning, not a block: click &amp;quot;Ignore &amp;amp; Proceed&amp;quot; on it and the phishing page is still there. Cloudflare also found the hosting layer for me: its reply named where the site actually lives, a provider called VIRTUO. That is the one layer the challenge wall cannot blind, because it is not fetching anything from outside, the files are sitting inside its own network. In theory it is the most effective cut of all. In practice I emailed them at 04:12 UTC on Sunday and have had no reply at all.&lt;/p&gt;
&lt;p&gt;At the naming layer I took three routes at once. The .blog registry replied that the case had been forwarded to the appropriate registrar for action, which is to say: not the registry's problem. The registrar, NameSilo, replied from its abuse mailbox that it does not act on emailed reports and that I should use its web form instead. And NetBeacon, the mediator that exists to route a report to the party who can act on it, produced a Cloudflare ticket and no registrar response at all.&lt;/p&gt;
&lt;p&gt;The third route was the one that worked. On Monday morning UTC I put the same evidence into that web form. At 08:53 the domain was still up, with no action recorded against it in RDAP. By 21:19 it carried &lt;code&gt;client hold&lt;/code&gt;, &lt;code&gt;server hold&lt;/code&gt; and &lt;code&gt;pending delete&lt;/code&gt;, its nameservers had been stripped, and it was gone from DNS. NameSilo wrote back to say it had deactivated the domain at 01:14 PM on the 17th, in its own local time. That moment matches the registry's record of the change to the second: twelve hours and thirty-seven minutes after I pressed submit. Its same-day sibling, &lt;code&gt;post-colombia.blog&lt;/code&gt;, went with it.&lt;/p&gt;
&lt;p&gt;The same evidence, to the same registrar: by email it bought a note telling me to use the form, and through the form it bought the deletion of the domain. The difference was not the evidence. It was which door it arrived at. And &lt;code&gt;envio-colombia.blog&lt;/code&gt; is still there. One coincidence lines up, though I cannot prove it is the reason: the two that were deleted were registered on the 15th and were still inside the grace period in which a registrar can delete a registration and be refunded in full, while envio was registered back in early July, long outside it.&lt;/p&gt;
&lt;p&gt;The genuinely opaque part is the scanner side. Several engines on VirusTotal flag this domain, and I have no way to tell whether any of those verdicts has anything to do with anything I filed: CRDF's own documentation states plainly that it does not disclose what a verdict was based on, and the rest do not offer even that much. Eleven channels went out, and not one of them lets me confirm that those verdicts were mine.&lt;/p&gt;
&lt;p&gt;The honest disclaimer, as always: this is one case, not a statistic. I could see inside this bot purely because this particular adversary wrote the key into a web page, and against one who keeps it server-side, this post would be half as long. The attribution is correlation, not proof. Aggregate reporting numbers are in &lt;a href=&quot;https://tg.pe/transparency&quot;&gt;tg.pe's transparency report&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A phishing machine that steers a victim live, and a visible drop group where the stolen data lands: it sounds frightening, but what it earns is still that customs fee, and the card behind it. The best defence is still the old advice: when a message says a parcel is stuck and asks for a small payment, do not click the link. Open the official site or app and check the tracking number yourself.&lt;/p&gt;
&lt;p&gt;The one thing worth carrying away is that 3-D Secure screen. When your banking app asks you to confirm a transaction, read the merchant and the amount it names, and check them against what you were actually doing. If they do not match, do not approve. And if the card number is already out, the rest is what everyone already knows: freeze the card, then read back through the last few charges.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Appendix: how tg.pe screens every link&lt;/h1&gt;
&lt;p&gt;Every submitted link passes through these gates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Before it goes live&lt;/strong&gt;: the destination is checked against local blocklists and a high-risk list; its domain age is looked up, and very new domains are distrusted by default; and it is screened against Google Safe Browsing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;After it goes live&lt;/strong&gt;: a background VirusTotal scan restricts the link automatically once multiple engines flag it as malicious; suspicious destinations have evidence captured automatically (screenshot and redirect chain).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always&lt;/strong&gt;: abuse@tg.pe takes reports from outside, and I triage them by hand; destinations confirmed malicious are reported onward to the parties that can act, as this post describes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The design, the numbers, and the parts that do not work yet are all in the transparency report linked above.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The previous case ended more cleanly than this one: a phishing domain in use 75 minutes after it was registered, and gone from DNS by that evening, pulled by the .TOP registry. The full record of that day is in &lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-en&quot;&gt;Someone used my URL shortener for phishing. The domain didn't last eight hours.&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Written by Sean Wei, who runs &lt;a href=&quot;https://tg.pe/&quot;&gt;tg.pe&lt;/a&gt;. If you want the full indicators for this case and the per-layer reporting and response times, or you run a shortener yourself and want to know how this screening pipeline works in practice: security@tg.pe.&lt;/p&gt;
</content:encoded>
    </item>
    <item>
      <title>一個假包裹網站，和操盤它的那六顆按鈕</title>
      <pubDate>Tue, 18 Aug 2026 08:00:00 +0000</pubDate>
      <description>一個假的哥倫比亞郵政網站，跟你要一筆小額海關費。你交出卡號的同一秒，另一頭有個人即時決定下一步要騙走你什麼。這是把那台機器、和歹徒那一側的操作介面一起還原的紀錄。</description>
      <link>https://blog.sean.taipei/2026/08/parcel-phishing-zh</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2026/08/parcel-phishing-zh</guid>
      <content:encoded>&lt;p&gt;「您的包裹被海關扣住，補繳一筆關稅才能放行。」這種訊息，你大概每個月都收到幾則。這篇拆解的是這套把戲的一種版本，目標是哥倫比亞人，仿冒當地國營郵政 4-72。平常真的會收到的釣魚網站多半很破，尤其仿冒政府機關的那些，一眼就看得出來。這套不是，它做得相當完整。而麻煩在你交出卡號之後：那一頭不只有自動化程式，還有個活人在等著。&lt;/p&gt;
&lt;p&gt;8/16（日）凌晨，有人拿我的 &lt;a href=&quot;https://tg.pe/&quot;&gt;tg.pe&lt;/a&gt; 短網址服務去縮一條連結（這個服務任何人都能用，不用註冊），目的地是 &lt;code&gt;paquetes-colombia.blog&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There's also an &lt;a href=&quot;https://blog.sean.taipei/2026/08/parcel-phishing-en&quot;&gt;English version&lt;/a&gt; of this post.&lt;/p&gt;
&lt;h1&gt;一個新網域，長得像政府網站&lt;/h1&gt;
&lt;p&gt;先看它有多新。查公開的網域註冊資料（RDAP），它註冊於台北時間 8/16 凌晨 1 點，3 小時後被送進 tg.pe。對這麼新的網域，tg.pe 預設先當蜜罐處理：投稿的人看到「建立成功」，連結在視窗內也照常轉址過去，但它只活幾分鐘就自我銷毀，之後再點就只剩 404。這套「新網域先不信任」的邏輯，&lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-zh&quot;&gt;上一篇&lt;/a&gt;寫過，這裡不贅述。&lt;/p&gt;
&lt;p&gt;把自己門口掃乾淨只是最低標。網域還活著，同一條連結照樣會從簡訊、Email 繼續傳，所以我照例人工點進去看一眼。這次看到的，比上次那種「一頁假登入」複雜得多。&lt;/p&gt;
&lt;p&gt;它是一整套網站，仿的是 4-72（哥倫比亞的國營郵政）：版面、字體全照抄，頁首掛著哥倫比亞政府入口 GOV.CO 的橫條，頁尾抄了 4-72 的稅籍編號。最偷懶的是網站小圖示（favicon）和那條 GOV.CO 橫條的圖，都是直接從 4-72 官網的伺服器上盜連過來的。這個偷懶有代價：仿冒站每被打開一次，就會替訪客向 4-72 的伺服器要一次那兩張圖，而請求裡的來源網址欄位寫的正是仿冒站自己。每一個冒用它的網域，此刻都躺在 4-72 自己的存取紀錄裡。被冒用的品牌手上其實有一份現成的冒用清單，只是幾乎沒人在監測。&lt;/p&gt;
&lt;p&gt;整個站躲在流量中介 Cloudflare 後面，而且防護等級被開到會跳驗證牆，那是歹徒主動在 Cloudflare 帳號裡開的設定，效果是：靠實際抓頁面判斷的掃描器全部只拿到一頁「請證明你不是機器人」，urlscan 給這個網域的網站評分是 0 分。不過失明的只有靠抓頁面的那幾家：urlscan 自家的機器學習引擎仍判它惡意（96 分），VirusTotal 在 tg.pe 收件的當下也已經有 1 家標惡意、1 家標可疑。那些判定不可能是從網頁內容來的，牆就擋在那裡；至於它們實際看了什麼，廠商不公開。&lt;/p&gt;
&lt;h1&gt;兩百塊的算計&lt;/h1&gt;
&lt;p&gt;查件頁不管你輸入什麼單號（只要長度合理），都回同一句話：你的包裹「Retenido en aduana」（扣在海關），要補繳關稅。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-customs.png&quot; alt=&quot;假的海關頁&quot;&gt;
&lt;em&gt;假的海關頁：金額 19,900 披索，搬出哥倫比亞真實存在的海關法規，再掛一句假的「DIAN（稅務暨海關總署）決議」虛張聲勢。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;19,900 披索約合新台幣 200 元，小到你不會為了它特地打電話去郵局查證，剛好落在「算了付一付」的區間。再配上真實的法令編號和政府機關，滿滿權威感。不過這 200 塊只是入場費，下一頁才是它要的。&lt;/p&gt;
&lt;h1&gt;一張每 3 秒等指令的付款表單&lt;/h1&gt;
&lt;p&gt;按下「繳費」，表單跳出來：持卡人姓名、信用卡號、有效期限、CVV（卡片背面的驗證碼）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-card.png&quot; alt=&quot;假的付款頁&quot;&gt;
&lt;em&gt;要害在這裡：一次要齊完整的信用卡資料。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;到這裡都還算常見，稀奇的是它背後的動作。從你打開的那一刻起，這頁每 3 秒向自己的伺服器問一次：「接下來要我把這個人帶去哪裡？」等的是一個人給它指令。&lt;/p&gt;
&lt;p&gt;因為在另一頭，你剛交出的卡號正即時送進一個 Telegram 群組，歹徒收到的那則訊息底下，附著一排按鈕。&lt;/p&gt;
&lt;h1&gt;歹徒手機上的那六顆按鈕&lt;/h1&gt;
&lt;p&gt;你在付款頁猶豫的這幾秒，另一頭有支手機震了一下：卡號跳出來，底下六顆按鈕，有人在挑下一步。就像這樣：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-panel.png&quot; alt=&quot;操作者手機上會看到的畫面（示意）&quot;&gt;
&lt;em&gt;操作者這一頭的畫面：底下六顆按鈕分別是簡訊驗證碼、Email 驗證碼、3D 驗證、卡片密碼、卡號無效、完成。這張是我用自己的機器人和測試資料重建的示意圖。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;這六顆按鈕不是我憑空猜的，付款頁的前端 JS 程式碼攤在明處，直接寫明了送去 Telegram 的訊息要附哪些按鈕，以下依實際擷取轉錄：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const keyboard = [
  [btn('📲 OTP SMS', 'redirect_sms'),  btn('📧 OTP Email', 'redirect_email')],
  [btn('🔒 3D Secure', 'redirect_vbv'), btn('🔢 PIN', 'redirect_pin')],
  [btn('❌ Tarjeta inválida','invalid_card'), btn('🏁 Finalizar','redirect_success')]
];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每顆按鈕都連到 &lt;code&gt;cmd.php?uid=&amp;lt;受害者編號&amp;gt;&amp;amp;cmd=&amp;lt;動作&amp;gt;&lt;/code&gt;。那是 Telegram 的「打開網址」按鈕，所以歹徒一按，是歹徒自己的瀏覽器去打 &lt;code&gt;cmd.php&lt;/code&gt;。他每下一個指令，都會在那台伺服器的存取紀錄裡留下自己的位址。這件事從外面完全看不到，只有那台伺服器的主人看得到。&lt;/p&gt;
&lt;p&gt;操作者按哪一顆，你的瀏覽器 3 秒內就會跳到對應的畫面。&lt;/p&gt;
&lt;p&gt;下面這張截圖不用交出卡號也拿得到：那些指令要把人帶到哪一頁，就寫在同一段 JS 程式碼裡，直接請求那些網址就看得到；只有「卡號無效」不換頁，是直接在原頁跳出錯誤訊息。&lt;/p&gt;
&lt;p&gt;他按下「簡訊驗證碼」，你的螢幕就跳出一格欄位，等你回填手機剛收到的那組數字。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/parcel-otp.png&quot; alt=&quot;假的簡訊驗證頁&quot;&gt;
&lt;em&gt;受害者看到的：一個等你填簡訊驗證碼的欄位。操作者只需要按一顆按鈕。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;按「卡號無效」，畫面說卡號打錯、請你重填，更陰險的是「3D 驗證」（刷卡時銀行另外跟你確認身分的那道手續）：你看到的畫面是「請到您的銀行 App 確認這筆交易」。這一步沒有偷走任何東西。它的用途是讓你在自己的銀行 App 裡，親手批准歹徒同時送出的那筆扣款，而你以為自己批准的是海關費。&lt;/p&gt;
&lt;p&gt;這一整套只為了一件事：他拿你的卡去刷，同一時間把銀行的每一道確認從你手上騙過來。銀行的檢查沒有任何一道被破解或被拿掉，每一道都照常執行、也都通過了，因為你本人就在線上，在它問的那一秒把答案交出去。簡訊驗證碼和 3D 驗證防的是盜刷的人不在現場，這套工具做的就是把你拉到現場。&lt;/p&gt;
&lt;h1&gt;按下按鈕的是誰&lt;/h1&gt;
&lt;p&gt;那個 Telegram 機器人的憑證（bot token）就明寫在網頁原始碼裡（&lt;code&gt;7362…&lt;/code&gt;），等於帳號密碼攤在每個訪客眼前。這不是非如此不可：這個站本來就有一支自己的 &lt;code&gt;api.php&lt;/code&gt; 在收卡號，發 Telegram 那一步大可一起在伺服器端做掉、把憑證藏起來。它會出現在你的瀏覽器裡，純粹是因為開發者懶。&lt;/p&gt;
&lt;p&gt;任何看得到原始碼的人，都能拿它去問這個機器人都在跟誰講話，所以我問了。整段查證只用 &lt;code&gt;getMe&lt;/code&gt;、&lt;code&gt;getUpdates&lt;/code&gt; 這兩個只讀不寫的功能：沒有送出任何指令，沒有碰過 &lt;code&gt;cmd.php&lt;/code&gt;（那會操控某個真實受害者的瀏覽器），也沒有在這個站送出過任何一筆資料。&lt;/p&gt;
&lt;p&gt;機器人叫「KING DE L'ATLAS」，法文的「阿特拉斯之王」。它待在兩個 Telegram 群組裡：一個叫「4-72 #1」，收的是「有人打開網站了」這種即時通知；另一個叫「COLOMBIE」（法文的哥倫比亞），偷到的卡就貼在那裡。&lt;/p&gt;
&lt;p&gt;但 Telegram 不會把機器人自己送出去的訊息回傳給我，我只看得到被操作者引用回覆的那幾則：6 張完整的卡，加一組當場被攔下來的簡訊驗證碼。確定至少有 6 筆，無法推斷他總共騙到多少人。&lt;/p&gt;
&lt;p&gt;這 6 張卡都通過卡號本身的 Luhn 校驗規則，開頭幾碼落在哥倫比亞發卡行配到的號段。這些信用卡資料我加密後單獨交給 colCERT（哥倫比亞國家資安應變中心），由他們轉給發卡行。能停卡、能把款項退回來的只有發卡行，那一步從來不在我手上。&lt;/p&gt;
&lt;p&gt;從訊息看出群裡至少有兩個帳號在對話，用的是法語，其中一個帳號的名稱是「馬格里布」方言的詞彙，機器人叫「阿特拉斯」之王，與北非的山脈同名。這些加起來指向法語圈的馬格里布，但那只是語言和命名的線索，不等於國籍或位置。這套工具的程式碼註解同樣是法文，跟群裡一致，所以就這個案子看，寫工具的和按按鈕的很可能是同一群人。&lt;/p&gt;
&lt;p&gt;他們的帳號、對話、彼此怎麼稱呼，查的時候都看得到，我沒有寫進來。基礎設施我會點名，對應到具體的人的帳號我不點：一來看到不等於證明，萬一那是盜來的帳號就冤枉了；二來這篇要檢討的是這套機制，貼帳號只會把焦點拉到抓人。&lt;/p&gt;
&lt;h1&gt;這只是 #1&lt;/h1&gt;
&lt;p&gt;那個群組的名字「4-72 #1」帶著一個編號。很少人會把唯一的東西叫做一號。&lt;/p&gt;
&lt;p&gt;順著查下去，&lt;code&gt;paquetes-colombia.blog&lt;/code&gt; 不是孤例。有一個 7 月就註冊的網域 &lt;code&gt;envio-colombia.blog&lt;/code&gt;，用的是一模一樣的工具，連查件頁那個預先填好的假單號 &lt;code&gt;CO587294163&lt;/code&gt; 都一字不差。&lt;/p&gt;
&lt;p&gt;而且我直接對它的頁面做了指紋比對：它把偷到的卡號用同一隻 Telegram 機器人送去同個群組。卡號送出的同時，這套工具還會拿前六碼去一個第三方服務反查發卡行和卡種，一起附在給歹徒的訊息裡，而兩個站用的是同一把金鑰。所以這兩個站不只是拿同一套工具，後端根本是同一個：前台換個名字，卡號進的是同一個群組。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;envio-colombia.blog&lt;/code&gt; 到 8/18（二）傍晚還活著，還躲在同一道驗證牆後面，連收卡的那一頁都照常開著。它跟 paquetes 是同一批通報送出去的：註冊局和註冊商在 8/16（日）上午的追報裡就收到它（初報只列了 paquetes，一個半小時後我把整個叢集補上去），流量中介、瀏覽器封鎖清單和威脅情資平台是 8/17（一）補送的。&lt;/p&gt;
&lt;h1&gt;我做了什麼&lt;/h1&gt;
&lt;p&gt;這條連結被自動處理掉之後，我把它整理成一份完整情資，8/16（日）發出初始通報，8/17（一）補齊其餘各層，一共往三個方向送。兩天下來，回應最快的是中間層。最該動的名字那一層繞了一大圈才動，動它的還不是我一開始敲的那扇門。能一刀切斷整條活動的那一層，到現在沒動。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;讓它被找得到。&lt;/strong&gt; 兩個資安圈共用的威脅情資平台：盧森堡資安應變中心 CIRCL 營運的 MISP 情資社群，還有 abuse.ch 的 ThreatFox。這一步不會讓網站消失，是讓下一個撞到同一批基礎設施的人查得到。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;讓它停掉。&lt;/strong&gt; 上游每一層能動手的：流量中介 Cloudflare、賣網域的註冊商 NameSilo、管理整個 .blog 的註冊局、實際放著檔案的代管商，還有操作機器人用的 Telegram。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;通知被影響的人。&lt;/strong&gt; 被仿冒的 4-72，和哥倫比亞的國家資安應變中心 colCERT。前面那 6 張卡就是走這條路加密交出去的，由他們轉給發卡行去通知持卡人。&lt;/p&gt;
&lt;p&gt;其中 Telegram 那一刀值得算清楚。停掉機器人不會讓這個網站停止蒐集卡號，卡號本來就同時寫進它自己伺服器上的 &lt;code&gt;api.php&lt;/code&gt;。但會拆掉即時中繼那一半：歹徒收不到卡片送達的通知，就按不出那六顆按鈕。而因為我比對過的那兩個門面共用同一支機器人，這一刀不只砍在一個網站上。&lt;/p&gt;
&lt;p&gt;機器人憑證、兩個群組和兩個操作者帳號，我在 8/16（日）上午九點多一起交給 Telegram。到 8/18（二）傍晚，56 小時過去，機器人還在線上，群組和帳號一個都沒被動過。停掉這一層，兩個站的中繼會同時斷。Telegram 沒有回覆。&lt;/p&gt;
&lt;p&gt;最快的是 Cloudflare。8/16（日）上午九點我送出檢舉，中午前這個網域前面就多了一頁「Suspected Phishing」（疑似釣魚）的警告：下界是我最後一次看到它還沒處置的 11 點 06 分，上界是它回信自陳已處置的 11 點 24 分。不過那是警告不是阻擋，點頁面上的「Ignore &amp;amp; Proceed」照樣進得到釣魚頁。代管商那一層也是 Cloudflare 幫我找到的：我檢舉之後收到的回信，指出網站實際落腳在一家叫 VIRTUO 的業者。這一層是唯一不受那道驗證牆影響的，因為它不從外面抓頁面，檔案就在它自己的網路裡。理論上它是最有效的一刀，實際上我 8/16（日）中午就寄了，到現在沒有任何回覆。&lt;/p&gt;
&lt;p&gt;名字那一層我同時走了三條路。.blog 註冊局回信說已經轉交適當的註冊商處理，也就是它自己不出手；註冊商 NameSilo 的 abuse 信箱回信說不收 email 通報，要我改走它的網頁表單；NetBeacon，一個專門幫通報者把案子送到能行動一方的中介，轉出來的結果是一張 Cloudflare 的案件單，沒換到任何註冊商回應。&lt;/p&gt;
&lt;p&gt;有用的只有第三條。8/17（一）下午三點半，我把同一份證據填進那張表單。當天下午四點五十三，網域還活著、RDAP 上沒有任何處置標記；隔天清晨再查，&lt;code&gt;client hold&lt;/code&gt;、&lt;code&gt;server hold&lt;/code&gt;、&lt;code&gt;pending delete&lt;/code&gt; 三個狀態都上了，名稱伺服器被拔掉，網域從 DNS 上消失。NameSilo 隨後回信，說它在當地時間 8/17 下午一點十四分停用了這個網域；那個時刻和註冊局紀錄上的異動時間對得到秒，換算下來是我按下送出之後的 12 小時 37 分。同一批消失的還有同日註冊的兄弟站 &lt;code&gt;post-colombia.blog&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;同一份證據、同一個註冊商，走 email 換來一封「請改用表單」，走表單換來整域刪除。差別不在證據，在收件的那道門。而 &lt;code&gt;envio-colombia.blog&lt;/code&gt; 到現在還在。有個對得上但我沒有證據的巧合：被刪掉的兩個都是 8/15 註冊、當時還在新註冊的寬限期內，那段期間註冊商刪掉網域可以全額退費；envio 是 7 月初註冊的，早就出了那個窗口。&lt;/p&gt;
&lt;p&gt;真正不透明的是掃描器那一側。VirusTotal 上把這個網域標成惡意的那幾家引擎，我無從知道它們的判定跟我送出去的任何一條通路有沒有關係：CRDF 的說明文件明寫它不揭露判定的來源，其餘幾家連這種等級的說明都沒有。送了十一條通路，卻沒有一條能讓我確認那些判定是不是自己換來的。&lt;/p&gt;
&lt;p&gt;照例誠實聲明：這是一個案例，不是統計。我能看進這個機器人這一側，純粹是因為這次的對手把金鑰寫在網頁裡；換一個把憑證藏在自己後端的對手，這篇就只剩前半段。歸因的部分只是關聯，不是證據。通報的彙總數字在 &lt;a href=&quot;https://tg.pe/transparency&quot;&gt;tg.pe 的透明度報告&lt;/a&gt;裡。&lt;/p&gt;
&lt;p&gt;一套能即時操控受害者的釣魚機制，加上一個看得見的收贓群，聽起來很唬人，但它賺的還是那筆海關費，和你之後那張卡。攔住它最有效的一步還是老話：收到「包裹卡關、補繳小額費用」的訊息，別點連結，自己開官網或 App 查單號。&lt;/p&gt;
&lt;p&gt;那個 3D 驗證的畫面值得多記一句。銀行 App 跳出「請確認這筆交易」的時候，先看它寫的金額和商家對不對得上你剛剛在做的事，對不上就不要按。卡號已經送出去的話，剩下的動作大家都知道：停卡，然後把最近幾筆帳看過一遍。&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;附錄：tg.pe 怎麼檢查每一條連結&lt;/h1&gt;
&lt;p&gt;每一條提交進來的連結，上線前後都會經過這些關卡：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;建立前&lt;/strong&gt;：先比對自家的封鎖與高風險網域名單；查詢網域的註冊年齡，太新的預設先不信任；再比對 Google Safe Browsing 的威脅資料庫。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;建立後&lt;/strong&gt;：背景跑 VirusTotal 掃描，多個引擎判定惡意就自動限制連結；可疑的目的地會自動留存證據（截圖與轉址鏈）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;常態&lt;/strong&gt;：abuse@tg.pe 接收外部通報，由我人工分流；確認惡意的目的地會往上通報給能處置的單位，就像這篇做的一樣。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些機制的設計、數字與還做不到的部分，同樣都在上面那份透明度報告裡。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;上一次的結局比這次乾脆：一個註冊 75 分鐘就被拿去縮網址的釣魚網域，傍晚就被 .top 註冊局從 DNS 上移除。那一天的完整紀錄在〈&lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-zh&quot;&gt;有人拿我的短網址釣魚，那個網域活不到 8 小時&lt;/a&gt;〉。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;本文作者 Sean Wei，經營 &lt;a href=&quot;https://tg.pe/&quot;&gt;tg.pe&lt;/a&gt;。想要本案的完整指標與各層通報時間軸，或你也在跑短網址服務、想知道這套篩選管線怎麼落地，歡迎來信 security@tg.pe。&lt;/p&gt;
</content:encoded>
    </item>
    <item>
      <title>Someone used my URL shortener for phishing. The domain didn't last eight hours.</title>
      <pubDate>Thu, 13 Aug 2026 14:10:00 +0000</pubDate>
      <description>A phishing domain went to work 75 minutes after registration, got flagged at submission, reported up the chain, and removed from DNS by the .TOP registry, all in one day.</description>
      <link>https://blog.sean.taipei/2026/08/phishing-en</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2026/08/phishing-en</guid>
      <content:encoded>&lt;p&gt;On the morning of 13 August (UTC), someone submitted a link to my URL shortener &lt;a href=&quot;https://tg.pe/&quot;&gt;tg.pe&lt;/a&gt;. The destination was &lt;code&gt;validationreq.top&lt;/code&gt;, a domain I had never seen before. My automated checks flagged it the moment it came in, for a simple reason: the domain was too new.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There's also a &lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-zh&quot;&gt;Mandarin version&lt;/a&gt; of this post. 台灣朋友歡迎左轉 &lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-zh&quot;&gt;中文版&lt;/a&gt;。&lt;/p&gt;
&lt;h1&gt;75 minutes from registration to abuse&lt;/h1&gt;
&lt;p&gt;How new? RDAP, the public lookup protocol for domain registration data, settles it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rdap validationreq.top
registration: 2026-08-13 02:12 UTC

# my own logs
submitted to tg.pe: 2026-08-13 03:29 UTC
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the standard phishing playbook: disposable domains, registered and put to work immediately, burned and replaced. But newness is one of the easiest signals there is. Legitimate services rarely send out links on a domain registered less than two hours ago, so tg.pe distrusts very new domains by default. The link was flagged at submission and held as a honeypot: it stayed live for only a few minutes before self-destructing, and after that returned nothing but 404s.&lt;/p&gt;
&lt;p&gt;Cleaning up my own doorstep is the bare minimum, though. The phishing page itself was still alive, and copies of the link spreading through SMS, email or other shorteners would still hurt people, so I wrote the case up and sent it out.&lt;/p&gt;
&lt;h1&gt;One button, and the scanners see nothing&lt;/h1&gt;
&lt;p&gt;The page impersonated flatmates.com.au, an Australian flatshare marketplace that bills itself as the country's biggest: right branding, right layout, and nothing on it but a &amp;quot;Verify&amp;quot; button. Click it, and a form asks for your card details.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/phishing-verify.png&quot; alt=&quot;What automated scanners see&quot;&gt;
&lt;em&gt;Everything an automated scanner sees: a brand mock-up and a verify button. &lt;a href=&quot;https://urlscan.io/result/019ff92a-b290-75a8-a3f4-e57e2e86dce3/&quot;&gt;urlscan's verdict&lt;/a&gt;: score 0, no classification.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The scanners in this chain do not click buttons. urlscan's capture shows exactly that button: score 0, no classification at all. The page does not cloak for scanners. It serves every visitor the same thing and keeps the payload one click away, which is how pages like this slip past automated detection. So a pair of human eyes is still needed at the end: I clicked, saw the form asking for card details, and classified it as phishing. I have no screenshot of that page, and no scan I could find has one either.&lt;/p&gt;
&lt;h1&gt;Reporting it to the right people&lt;/h1&gt;
&lt;p&gt;Next it went out to everyone who could act on it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CIRCL MISP&lt;/strong&gt;: MISP is the open-source threat-intelligence sharing platform. CERTs, SOCs and security vendors exchange indicators there as structured events that correlate automatically against other members' data; this instance is run by CIRCL, the CERT for Luxembourg's private sector, communes and non-governmental entities. I published the domain as a full event: registration time, behaviour, evidence, and later the takedown outcome. The community is not open to the public, so here is a screenshot.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/phishing-misp.png&quot; alt=&quot;The MISP event&quot;&gt;
&lt;em&gt;The event on CIRCL MISP: indicators, taxonomy tags, and the takedown timeline added afterwards.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The registration layer&lt;/strong&gt;: two parties can act on a domain itself. The registrar is the shop that sold the name; the registry runs the whole &lt;code&gt;.top&lt;/code&gt; zone. I reported to the registrar via &lt;a href=&quot;https://netbeacon.org/&quot;&gt;NetBeacon&lt;/a&gt;, the DNS abuse reporting relay, and emailed the .TOP registry's abuse desk directly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure and browsers&lt;/strong&gt;: the site sat behind Cloudflare, so their abuse form; Google Safe Browsing and Microsoft SmartScreen, which between them power the warning pages in every major browser; and Netcraft, whose phishing feed and takedown service reach a lot of places I cannot. I also emailed the impersonated brand's security team.&lt;/p&gt;
&lt;p&gt;Then the responses came in. Cloudflare moved fastest, blocking the reported URL in under half an hour. But every time I visited, this phishing page handed out a fresh random path, so blocking a single URL cannot keep up. That is not on Cloudflare; URL-level blocking is the wrong granularity for a site that changes paths on demand.&lt;/p&gt;
&lt;p&gt;What ended it was the registry. At 09:46 UTC, about 3 hours 20 minutes after the report, the .TOP registry replied:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We have reviewed the provided domains and applied the serverHold status, effectively suspending their resolution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;serverHold is a registry-level freeze: the registry stops publishing the domain's delegation, so the name drops out of the &lt;code&gt;.top&lt;/code&gt; zone and stops resolving. The registration record still exists and the registry can lift the status, but for as long as it is set, the name is dead on the network.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rdap validationreq.top | grep status
status: client transfer prohibited, server hold

$ dig +short validationreq.top
(no answer)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;.top&lt;/code&gt; has a certain reputation in the security community, usually associated with cheap bulk registrations and heavy abuse. This time its abuse desk replied and acted the same day, and that deserves to be said in public.&lt;/p&gt;
&lt;p&gt;The registrar path is the one that stayed quiet: the report relayed via NetBeacon had drawn no reply by the time the registry acted. No reply is not the same as no action: a report that travels through a relay and then into a registrar's own queue has more steps between me and whoever ends up handling it. I am recording it, not drawing a conclusion from it.&lt;/p&gt;
&lt;h1&gt;The timeline&lt;/h1&gt;
&lt;p&gt;All in one day, times in UTC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;02:12&lt;/strong&gt; &lt;code&gt;validationreq.top&lt;/code&gt; registered&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;03:29&lt;/strong&gt; link submitted to tg.pe; flagged at submission&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;05:57&lt;/strong&gt; threat-intel event published on MISP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;06:25&lt;/strong&gt; reports filed (NetBeacon, .TOP registry, Cloudflare, Google Safe Browsing, Microsoft SmartScreen, Netcraft)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;06:47&lt;/strong&gt; Cloudflare URL-level block confirmed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;09:46&lt;/strong&gt; .TOP registry confirms serverHold; the domain stops resolving&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From registration to confirmed removal from DNS: 7 hours and 34 minutes.&lt;/p&gt;
&lt;h1&gt;Two months ago, I said I wanted to do this&lt;/h1&gt;
&lt;p&gt;In June, at TWIGF (the Taiwan Internet Governance Forum), I gave a lightning talk and told a story: a stranger in Germany emailed me about a fake parcel-delivery link on my service, and I verified it, removed it, and replied within 50 minutes. He was surprised, because in his experience the same report to a big platform disappears into a void. And I said what I wanted to do next: spot brand-new phishing domains the moment they are first used on my service, verify them by hand, and report them to the right people.&lt;/p&gt;
&lt;p&gt;Two months later, it happened, end to end.&lt;/p&gt;
&lt;p&gt;URL shorteners occupy a strange position in the reporting chain: attackers hand you their freshest links themselves. Scanners have to comb the entire internet for phishing pages; I only have to watch my own submission queue. This domain went from registered to flagged in 75 minutes, not because I scan faster than anyone, but because the attacker brought it to me.&lt;/p&gt;
&lt;p&gt;The honest disclaimer, as always: this is one case, not a statistic. The previous loop like this took eight days to close, and some reports sink without a trace. Killing one domain in a single day does not prove that reporting usually works. It proves the path exists, and that sometimes it is astonishingly fast. The full reporting record and numbers are in tg.pe's &lt;a href=&quot;https://tg.pe/transparency#closed-loop&quot;&gt;transparency report&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Appendix: how tg.pe screens every link&lt;/h1&gt;
&lt;p&gt;tg.pe is a free URL shortener run by one person. Every submitted link passes through these gates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Before it goes live&lt;/strong&gt;: the destination is checked against local blocklists and a high-risk list; its domain age is looked up, and very new domains are distrusted by default; it is screened against Google Safe Browsing; and suspicious ad-redirect patterns are held for observation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;After it goes live&lt;/strong&gt;: a background VirusTotal scan can restrict the link automatically; suspicious destinations get evidence captured automatically (screenshot and redirect chain); and links that have not been checked for a while are re-checked on their next click.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always&lt;/strong&gt;: abuse@tg.pe takes external reports, triaged by hand; destinations confirmed malicious are reported onward to the parties that can act, exactly as this post describes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The design, the numbers and the parts that do not work yet are all in the same transparency report.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Three days later someone put another phishing link through tg.pe, and that one did not end as cleanly: a fake parcel site impersonating Colombia's national postal service, with a live operator on the other end choosing what to take from you next. The naming layer took a day and a half to act. The full record is in &lt;a href=&quot;https://blog.sean.taipei/2026/08/parcel-phishing-en&quot;&gt;A fake parcel site, and the six buttons that run it&lt;/a&gt;.&lt;/p&gt;
</content:encoded>
    </item>
    <item>
      <title>有人拿我的短網址釣魚，那個網域活不到 8 小時</title>
      <pubDate>Thu, 13 Aug 2026 14:00:00 +0000</pubDate>
      <description>一個註冊 75 分鐘就上工的釣魚網域，當天上午被自動擋下，傍晚就被 .top 註冊局從 DNS 上移除。這是那一天的完整紀錄。</description>
      <link>https://blog.sean.taipei/2026/08/phishing-zh</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2026/08/phishing-zh</guid>
      <content:encoded>&lt;p&gt;8/13（四）上午，有人在我的短網址服務 &lt;a href=&quot;https://tg.pe/&quot;&gt;tg.pe&lt;/a&gt; 提交了一條連結，目的地是 &lt;code&gt;validationreq.top&lt;/code&gt;，一個我沒見過的網域。自動檢查在提交的當下就把它標記起來，理由只有一個，這個網域太新了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There's also an &lt;a href=&quot;https://blog.sean.taipei/2026/08/phishing-en&quot;&gt;English version&lt;/a&gt; of this post.&lt;/p&gt;
&lt;h1&gt;註冊 75 分鐘就上工&lt;/h1&gt;
&lt;p&gt;新到什麼程度？查 RDAP（網域註冊資料的公開查詢協定），註冊時間是同一天上午 10 點 12 分，距離被提交到 tg.pe 只有 75 分鐘。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rdap validationreq.top
registration: 2026-08-13 10:12 (UTC+8)

# tg.pe 自己的紀錄
提交到 tg.pe:  2026-08-13 11:29 (UTC+8)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這是釣魚集團的標準作業：拋棄式網域，註冊完立刻上工，被封了就換下一個。但「剛出生」本身就是最好認的特徵，一個正常的服務很少會用註冊不到兩小時的網域發連結，所以 tg.pe 對太新的網域一律先不信任。這條連結被當成蜜罐，只活了幾分鐘就自我銷毀，之後再點就只剩 404。&lt;/p&gt;
&lt;p&gt;把自己門口掃乾淨只是最低標。釣魚頁本體還活著，從簡訊、Email 或其他短網址流出去的連結照樣害人，所以我把它整理成通報，往外送。&lt;/p&gt;
&lt;h1&gt;一顆按鈕，掃描器就什麼都看不到&lt;/h1&gt;
&lt;p&gt;這個頁面仿冒的是 flatmates.com.au，一個找室友、分租房間的澳洲平台，自稱全澳最大。品牌、版面都像，內容只有一顆「Verify」按鈕。按下去，才會出現要你填信用卡號的表單。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/phishing-verify.png&quot; alt=&quot;自動掃描器看到的畫面&quot;&gt;
&lt;em&gt;自動掃描器看到的全部：一個品牌假頁和一顆驗證按鈕。&lt;a href=&quot;https://urlscan.io/result/019ff92a-b290-75a8-a3f4-e57e2e86dce3/&quot;&gt;urlscan 的判定&lt;/a&gt;：0 分，未給任何分類。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;自動掃描器通常不會去按按鈕，urlscan 的快照拍到的就是那顆按鈕：0 分、沒有任何分類。它沒有針對掃描器變臉，對所有訪客送的都是同一頁，只是把要害藏在一次點擊之後，這類釣魚頁就是這樣穿過自動偵測的。所以最後還是得有人真的點進去看一眼：我自己點過去，看到那張要卡號的表單，才確定它是釣魚。那一頁的截圖我沒有，掃描器也沒有。&lt;/p&gt;
&lt;h1&gt;通報給對的人&lt;/h1&gt;
&lt;p&gt;接下來把情報送給每一個能動手的單位：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CIRCL MISP&lt;/strong&gt;：資安圈交換威脅情資的開源平台，成員把惡意網址、網域整理成固定格式的事件丟上去，平台自動跟其他人回報的資料串起來；這裡用的是盧森堡資安應變中心 CIRCL 營運的那一個。我把這個網域發成一筆完整事件：註冊時間、行為描述、佐證連結，後來又補上了下架結果。這個社群不對一般公眾開放，所以附一張截圖。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.sean.taipei/2026/08/phishing-misp.png&quot; alt=&quot;MISP 事件截圖&quot;&gt;
&lt;em&gt;發到 CIRCL MISP 的事件：惡意網址與網域、分類標籤，和事後補上的下架時間軸。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;網域註冊層&lt;/strong&gt;：一個網域有兩層人管得動，註冊商（registrar）是把網域賣給你的那家店，註冊局（registry）是整個 &lt;code&gt;.top&lt;/code&gt; 的管理者。我透過專門轉送 DNS 濫用通報的 &lt;a href=&quot;https://netbeacon.org/&quot;&gt;NetBeacon&lt;/a&gt; 通報註冊商，同時直接寫信給 &lt;code&gt;.top&lt;/code&gt; 註冊局的濫用通報窗口。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;基礎設施與瀏覽器&lt;/strong&gt;：網站躲在 Cloudflare 後面，送了 Cloudflare 的 abuse 表單；Google Safe Browsing 和 Microsoft SmartScreen 負責讓各家瀏覽器跳警告；Netcraft 則是專門追蹤下架進度的公司，它的釣魚名單餵給很多我碰不到的地方。也寄了一封信給被仿冒平台的資安窗口。&lt;/p&gt;
&lt;p&gt;各方的反應陸續進來。最快的是 Cloudflare，不到半小時就擋下了我通報的那條 URL；不過這個釣魚頁我每次打開都被丟到一條新的隨機網址，只擋其中一條，效果有限。這不是 Cloudflare 的問題，是 URL 層級的封鎖天生跟不上會換路徑的網站。&lt;/p&gt;
&lt;p&gt;把它結束掉的是註冊局。下午 5 點 46 分，通報後約 3 小時 20 分，&lt;code&gt;.top&lt;/code&gt; 註冊局回信：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We have reviewed the provided domains and applied the serverHold status, effectively suspending their resolution.&lt;/p&gt;
&lt;p&gt;（我們已審查你回報的網域，並套用 serverHold 狀態，實質上暫停了它的解析。）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;serverHold 是註冊局層級的凍結，直接把這個名字從 &lt;code&gt;.top&lt;/code&gt; 的名冊上劃掉，之後不管誰來查都查不到。註冊紀錄還在，註冊局也可以解除；但只要掛著，這個網域在網路上就是死的。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rdap validationreq.top | grep status
status: client transfer prohibited, server hold

$ dig +short validationreq.top
（沒有任何回應）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;.top&lt;/code&gt; 在資安圈的印象，通常和便宜、大量註冊、濫用綁在一起。但這次它的濫用通報窗口當天回信、當天處置，值得公開記一筆。&lt;/p&gt;
&lt;p&gt;沒回音的是註冊商那條線：經 NetBeacon 轉送的那份通報，到註冊局動手時都還沒有回信。沒回信不等於沒動作，一份報告經過轉送、再排進註冊商自己的處理流程，中間的環節本來就多，這裡只是照實寫下來。&lt;/p&gt;
&lt;h1&gt;時間軸&lt;/h1&gt;
&lt;p&gt;全部發生在同一天（台北時間）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;10:12&lt;/strong&gt; &lt;code&gt;validationreq.top&lt;/code&gt; 註冊&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;11:29&lt;/strong&gt; 連結被提交到 tg.pe，自動檢查即時標記&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;13:57&lt;/strong&gt; 於 MISP 情資平台發布事件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;14:25&lt;/strong&gt; 各通路通報送出（NetBeacon、.top 註冊局、Cloudflare、Google Safe Browsing、Microsoft SmartScreen、Netcraft）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;14:47&lt;/strong&gt; 確認 Cloudflare 已擋下通報的 URL&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;17:46&lt;/strong&gt; .top 註冊局回信確認已套用 serverHold，網域停止解析&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;從註冊，到確認它從 DNS 上消失，7 小時 34 分。&lt;/p&gt;
&lt;h1&gt;兩個月前，我說過想做這件事&lt;/h1&gt;
&lt;p&gt;六月在 TWIGF（台灣網路治理論壇）的 lightning talk，我講了一個故事：有個素不相識的德國人寫信告訴我，我的服務上有一條假包裹簡訊的連結，我在 50 分鐘內查證、下架、回信。他嚇了一跳，因為以他的經驗，同樣的信寄給大平台通常石沉大海。當時我說，接下來想做的是：在全新的釣魚網域第一次被拿來縮網址的當下就抓到它，人工確認，然後通報給對的人。&lt;/p&gt;
&lt;p&gt;兩個月後，這件事完整發生了一次。&lt;/p&gt;
&lt;p&gt;短網址服務在通報鏈上有一個奇特的位置：攻擊者會自己把最新鮮的釣魚連結送上門。掃描器得在整個網路上大海撈針，我只要盯著自己收到的那幾條連結。這個網域從註冊到被標記只花了 75 分鐘，不是因為我掃得比誰快，是因為攻擊者自己送過來了。&lt;/p&gt;
&lt;p&gt;照例誠實聲明：這是一個案例，不是統計。上一次同樣走完整條路，花了八天，也有通報送出去就沒了下文的。一個下午殺掉一個網域，證明不了「通報通常有用」，它只證明這條路存在，而且有時候快得驚人。完整的通報紀錄和數字，都在 tg.pe 的 &lt;a href=&quot;https://tg.pe/transparency#closed-loop&quot;&gt;透明度報告&lt;/a&gt; 裡。&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;附錄：tg.pe 怎麼檢查每一條連結&lt;/h1&gt;
&lt;p&gt;tg.pe 是我一個人營運的免費短網址服務。每一條提交進來的連結，上線前後都會經過這些關卡：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;建立前&lt;/strong&gt;：目的地先比對自家的封鎖與高風險網域名單；查詢網域的註冊年齡，太新的一律先不信任；再比對 Google Safe Browsing 的威脅資料庫；可疑的廣告轉址樣式會被攔下觀察。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;建立後&lt;/strong&gt;：背景跑 VirusTotal 掃描，命中就自動限制連結；可疑目的地會自動留存證據（截圖與轉址鏈）；太久沒複查的連結，會在下一次被點擊時重新檢查一遍。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;常態&lt;/strong&gt;：abuse@tg.pe 接收外部通報，人工分流處理；確認惡意的目的地會往上通報給能處置的單位，就像這篇文章做的一樣。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些機制的設計、數字與還做不到的部分，同樣都在上面那份透明度報告裡。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;三天後又有人拿 tg.pe 縮了一條釣魚連結，那次沒這麼乾脆。仿冒的是哥倫比亞的國營郵政，你交出卡號的同一秒，另一頭有個活人在挑下一步要騙走你什麼。名字那一層拖了一天半才動手。完整紀錄在〈&lt;a href=&quot;https://blog.sean.taipei/2026/08/parcel-phishing-zh&quot;&gt;一個假包裹網站，和操盤它的那六顆按鈕&lt;/a&gt;〉。&lt;/p&gt;
</content:encoded>
    </item>
    <item>
      <title>開始滑冰才知道的幾件事</title>
      <pubDate>Fri, 17 Jul 2026 00:20:00 +0000</pubDate>
      <description>花式滑冰場邊撿來的七條小知識：洗冰車為什麼用熱水、冰刀怎麼咬冰、跌倒為什麼傷手腕，以及花式滑冰為什麼在夏季奧運出道。BlogBlog 同樂會 7 月主題投稿。</description>
      <link>https://blog.sean.taipei/2026/07/skating</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2026/07/skating</guid>
      <content:encoded>&lt;blockquote&gt;
&lt;p&gt;這是我的「&lt;a href=&quot;https://blogblog.club/party/&quot;&gt;BlogBlog 同樂會 - 2026 年 7 月&lt;/a&gt;」的投稿文章。本月主題是「&lt;a href=&quot;https://shuaixin.cc/Fun-Fact/&quot;&gt;有趣的小知識或冷門概念&lt;/a&gt;」，由劉昕主持。如果你有自己的部落格，歡迎一起來參加！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我的休閒嗜好之一是花式滑冰，在場邊學到不少有趣的小知識。以下挑七條我最喜歡的，多數都有點反直覺。&lt;/p&gt;
&lt;h1&gt;1. 洗冰車先把冰刮掉，再用熱水重結一層&lt;/h1&gt;
&lt;p&gt;中場休息時開出來、慢慢繞圈的那台機器（俗稱洗冰車），做的事比看起來精緻。它會先用一片大刀把表層磨損的冰「刮掉」一層、把刮下來的冰屑收走，再灑上一層接近 60 度的熱水，讓它重新結成光滑的新冰。&lt;/p&gt;
&lt;p&gt;為什麼是熱水？因為熱水裡溶的空氣比冷水少，結冰時不會困住一堆小氣泡，凍出來的冰反而更硬、更透，表面也更平；而且熱水會先把舊冰面稍微融一下，新的一層才「黏」得上去，不會像一張鬆掉的皮浮在表面。附帶一提，同一座冰場，花式滑冰會把冰調得稍微軟一點，方便起跳、落冰咬得住；冰球則要更硬更冷，滑得快，球的反應也穩。&lt;/p&gt;
&lt;h1&gt;2. 冰刀鞋的「鞋」和「刀」是分開買的，刀片每一段還各有講究&lt;/h1&gt;
&lt;p&gt;到了一定程度，你的冰刀鞋不是一體成形的：「鞋子」和底下的「刀」是分開買、分開換的，由店家幫你把刀鎖到鞋底、還要抓對位置。&lt;/p&gt;
&lt;p&gt;那片刀每一段各有分工，不是一條均勻的直邊。最前端那排鋸齒叫刀齒，是拿來起跳和旋轉的，不是煞車用的，新手常誤踩它而絆倒；刀的前後是一條微微的弧線，真正接觸冰面的只有中間短短一段，滑行、轉彎、旋轉分別踩在不同位置；連刀底都磨了一道內凹的溝，溝的深淺也是取捨：磨得深，咬冰穩但比較費力；磨得淺，滑得快但比較不抓。一片看起來平平無奇的刀，其實藏了一整套「抓地」和「順滑」之間的權衡。&lt;/p&gt;
&lt;h1&gt;3. 冰刀有兩條刃，前進是靠往「側邊」推的&lt;/h1&gt;
&lt;p&gt;很多人以為溜冰是踩在一條像刀鋒一樣的細線上，其實冰刀的底部中間，就是上一條提到的那道內凹溝，溝的兩側各留一個邊，分別叫內刃和外刃，真正咬住冰的是這兩條邊。整片刀刃只有 4 毫米寬，比直覺來得鈍、穩定，說它像菜刀的「刀背」，其實比刀鋒更貼切。&lt;/p&gt;
&lt;p&gt;那要怎麼前進？像跑步那樣直直往後蹬，刀只會順著刀身的方向打滑，吃不到什麼力。當然，絕大多數新手還是這樣動起來的：腳自然開成外八、小步小步往後蹬，難看又費力，但會動。它會動的原因是：外八正好讓刀刃斜著咬住了冰，你等於在不知不覺中做了正確動作的粗糙版。真正的滑行只是把同一件事做徹底，讓刀刃斜著咬進冰、往「側邊」用力一推，把自己送出去。所以滑冰前進的方向，和施力的方向其實是垂直的；從外八碎步到真正會滑，差別只在把「往側邊推」做得夠乾脆。&lt;/p&gt;
&lt;h1&gt;4. 很多「學不會」的新手，其實只是鞋帶沒綁緊&lt;/h1&gt;
&lt;p&gt;冰刀鞋要把整個腳踝牢牢固定住，你的力量才傳得到刀刃上；鞋帶一鬆，腳踝在鞋子裡晃，你使的力先被那點空隙吃掉大半，人就會覺得「站不穩、使不上力、根本學不會」。&lt;/p&gt;
&lt;p&gt;很多人第一次溜冰，就以為自己天生沒有平衡感，其實只是鞋帶差了那麼幾格。把鞋帶綁緊，尤其腳踝那一段，同一個人常常像換了一雙腳。&lt;/p&gt;
&lt;h1&gt;5. 最多人受傷，不是因為滑太快，是因為跌倒時「用手去撐」&lt;/h1&gt;
&lt;p&gt;在溜冰場最常見的骨折，不在腳，在手腕。人一失去平衡，反射動作就是把手往前一撐去接地，全身的重量壓上去，前臂靠手腕那截骨頭（橈骨）就成了最常斷的地方。真正危險、但其實比較少見的，是整個人往後仰、後腦直接磕上冰面。&lt;/p&gt;
&lt;p&gt;所以教練一開始教的往往不是怎麼滑，而是怎麼「跌」：收手、側身、順勢往屁股坐下去，別用手硬撐。冰面比多數人想的硬得多，先學會跌倒，其實比先學會滑還重要。&lt;/p&gt;
&lt;h1&gt;6. figure skating 的 figure 是「圖形」，這項運動本來是比誰畫得圓&lt;/h1&gt;
&lt;p&gt;最後兩條是翻資料才知道的。花式滑冰的英文 figure skating，那個 figure 不是「身材」也不是「人物」，就是字面上的「圖形」。這項運動最早比的，是在冰上用刀刃「畫圖」：選手反覆描出 8 字形等規定圖形，裁判蹲下來、甚至貼近冰面，檢查冰痕畫得圓不圓、每一圈描得準不準。這種「強制圖形」曾佔總分的六成，練起來出了名地枯燥，選手一天可以花上幾小時安靜地畫圈。&lt;/p&gt;
&lt;p&gt;後來電視轉播興起，觀眾想看的是跳躍和旋轉，沒有人想看選手低著頭畫圈，圖形的比重就一路被砍，1990 年之後從國際賽場上徹底消失。比賽內容早就換過了，名字卻留在原地。中文的「花式」看不出這段身世，英文的 figure 倒是老老實實記著：它本來是一項畫圖的運動。&lt;/p&gt;
&lt;h1&gt;7. 花式滑冰是在「夏天」的奧運出道的&lt;/h1&gt;
&lt;p&gt;花式滑冰是史上第一個進入奧運的「冬季」運動，可是它第一次亮相，居然是在 1908 年倫敦的夏季奧運。&lt;/p&gt;
&lt;p&gt;原因很樸素：現代奧運 1896 年在雅典首辦時，根本還沒有冬季奧運，那要到 1924 年才在法國霞慕尼誕生，想比冰上項目，只能掛在夏季奧運底下。選手當然不是真的在大熱天的戶外滑，比賽場地是室內人工冰場，但掛的招牌，確確實實是夏季奧運。&lt;/p&gt;
&lt;p&gt;第二個跟進的冬季運動是冰球，1920 年在安特衛普的夏季奧運首度登場，而且那是冰球唯一一次出現在夏奧。1924 年冬奧成立後，這兩項一起搬了進去，一路留到今天。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;滑冰好玩的地方就在這：它看起來只是「在冰上滑」，可是從冰怎麼重鋪、那片刀怎麼設計，到它是怎麼一路從夏季奧運滑進冬季奧運的，每一件小事背後都有一個「原來如此」。而其中大部分，是真的踩上去、摔過幾次之後才會慢慢懂的。&lt;/p&gt;
&lt;p&gt;如果看完想親自上冰試試，我把台灣各冰場的票價、時段和新手須知整理成了一個小網站：&lt;a href=&quot;https://skating.tw/&quot;&gt;台灣滑冰指南&lt;/a&gt;。&lt;/p&gt;
</content:encoded>
    </item>
    <item>
      <title>Robust UDP Challenge - 網路程式設計概論</title>
      <pubDate>Thu, 15 Dec 2022 02:00:00 +0000</pubDate>
      <description>在掉包率 50%、延遲 100 毫秒的環境下，挑戰最快傳完 1,000 個檔案。</description>
      <link>https://blog.sean.taipei/2022/12/netprog</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2022/12/netprog</guid>
      <content:encoded>&lt;h1&gt;前情提要   {#recap}&lt;/h1&gt;
&lt;p&gt;這學期修習黃俊穎老師開設的網路程式設計概論（網程設），前半學期教了如何用 TCP 從簡單的 socket 應用，到實作較為複雜的 IRC 伺服器。&lt;/p&gt;
&lt;p&gt;這次第 12 周的實驗內容讓大家用兩週的時間，寫出能抵抗惡劣網路環境的 UDP 程式，完整傳送 1,000 個平均 16 KB 的檔案。&lt;/p&gt;
&lt;h2&gt;實驗限制   {#limit}&lt;/h2&gt;
&lt;p&gt;這次評測端使用 &lt;a href=&quot;https://man7.org/linux/man-pages/man8/tc-netem.8.html&quot;&gt;tc-netem (8)&lt;/a&gt; 製造出不穩定的網路環境，限制如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;封包有 40% 機率會遺失、10% 機率損毀&lt;/li&gt;
&lt;li&gt;延遲 50 ms - 150 ms&lt;/li&gt;
&lt;li&gt;網速上限 10 Mbps&lt;/li&gt;
&lt;li&gt;封包大小上限 1,500 bytes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在這樣的環境下，如果不特別做處理，基本上是傳不了檔案的，也因此是考驗各組技術的地方。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/netem-ping.png&quot; alt=&quot;使用 ping 測試的結果（封包來回需乘二）&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;使用 ping 測試的結果（封包來回需乘二）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;最初的想法   {#init}&lt;/h2&gt;
&lt;p&gt;在開始寫程式之前，當然是要先設計自己的通訊協定原型。原本規劃好了整套如何取得目錄、如何得知檔名及內容的協議，不過愈想愈覺得在這次的實驗中，分檔案慢慢傳反而沒效率。&lt;/p&gt;
&lt;p&gt;因此後來決定把寫好的協議及寫到一半的程式碼全部刪掉，從頭開始設計當成單一檔案傳輸的方法。&lt;/p&gt;
&lt;h1&gt;封包結構   {#format}&lt;/h1&gt;
&lt;p&gt;實驗環境 MTU 只允許每個封包傳送至多 1,500 bytes 的內容，因此會需要切成不同區塊，本次設計的封包結構前 2 bytes 是區塊編號。&lt;br&gt;
每個小封包扣掉 IP 層標頭的 20 bytes 及 UDP 層標頭的 8 bytes，再扣掉 2 bytes 的區塊編號後，共有 1,470 bytes 可供存放資料。&lt;/p&gt;
&lt;p&gt;在我的作法中，是先合併出一個大封包。大封包最前面的數字是總區塊數，後面接著 1,000 個數字是各檔案的尺寸，再來各檔案內容直接連接在後，以節省填充內容佔用的空間。&lt;/p&gt;
&lt;p&gt;也因為老師保證檔案大小在 32,000 bytes 以下，最極端的例子封包數也不會超過 22,000 個，因此只需要 2 bytes 的空間（-32768 ~ 32767）即可儲存。後面再接上所有檔案，合併後一個大封包總共約 16 MB 大小。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/udp-header.png&quot; alt=&quot;本次定義的標頭檔&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;本次定義的標頭檔&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;傳送邏輯   {#logic}&lt;/h1&gt;
&lt;p&gt;在相當穩定的環境下，我們可以只傳送不確認；在反應迅速的環境下，我們可以等收到確認封包再進行下一步；但在這次既慢又不穩的環境下，兩種做法效率都不會太好。&lt;/p&gt;
&lt;p&gt;因此我採用的方式是發送端自行估算在恰好頂到速度上限時，每隔多久可以發送一個封包。&lt;br&gt;
而接收端確認的方式，則是定期告訴發送端目前順利收到哪些封包了。&lt;/p&gt;
&lt;h2&gt;發送端詳細邏輯   {#sender}&lt;/h2&gt;
&lt;p&gt;對發送端來說，如果封包傳得太急，會踩到 10 Mbps 速率上限，導致緩衝區愈來愈長，封包需要排隊才能送出。&lt;br&gt;
如果因此造成多餘的延遲，讓確認封包也塞在緩衝區，最終導致無謂的時間浪費和送出更多重複的區塊，因此我們要找出適當的發送頻率以達到最佳平衡。&lt;/p&gt;
&lt;p&gt;以我的實作來說，每個封包都是吃滿 1,500 bytes 上限，多數流量來自發送端，來自接收端的確認封包佔少數。&lt;br&gt;
在撰寫本文之前，埋頭寫程式都沒去認真計算理論值，經過測試得出發送端大約需延遲 0.756 毫秒，恰好是碰到速率上限的甜蜜點。&lt;/p&gt;
&lt;p&gt;對於總共 16 MB 的檔案，為了符合最大傳輸上限 1,500 bytes 限制，分割後大約有 11,500 個區塊需要傳輸。&lt;br&gt;
最開始接收端什麼都沒有，因此先全部都發送一輪（約需 8.5 秒），之後再透過接收端回傳的確認封包，看哪些區塊未順利送達，再次依序發送。&lt;/p&gt;
&lt;p&gt;理想狀況中，每輪需要發送的區塊數量減半，所需時間也跟著減半。不過加上考慮延遲後，大約第六七輪開始，確認封包會來不及回傳。&lt;/p&gt;
&lt;h2&gt;接收端詳細邏輯   {#receiver}&lt;/h2&gt;
&lt;p&gt;發送確認封包的方式有許多不同做法，依筆者心中的效率簡單排序，由低到高大致為：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;收到每個區塊時，都單獨回傳確認（可能較差）&lt;/li&gt;
&lt;li&gt;收到數個區塊後，用一個封包，批量進行確認&lt;/li&gt;
&lt;li&gt;每隔一段時間，用多個封包，回傳伺服器的完整狀態&lt;/li&gt;
&lt;li&gt;每隔一段時間，用多個封包，回傳所有收過的區塊編號&lt;/li&gt;
&lt;li&gt;每隔一段時間，用一個封包，回傳新收到了哪些區塊&lt;/li&gt;
&lt;li&gt;每隔一段時間，用一個封包，以 bitset 回傳伺服器狀態（可能較佳）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此在最終的版本中，我是以 bitset 形式回傳接收端的狀態，每次只需要一個封包即可完成。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/status-bitset.png&quot; alt=&quot;使用 bitset 儲存、傳送狀態&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;使用 bitset 儲存、傳送狀態&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;有思考過在最後剩下不到 500 個未完成區塊的時候，或許直接回傳近期收到的區塊編號可以再更節省流量，不過感覺實作相對麻煩就作罷了。&lt;/p&gt;
&lt;h1&gt;延遲詳細計算   {#delay}&lt;/h1&gt;
&lt;p&gt;已知條件為：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每個封包 1,500 bytes&lt;/li&gt;
&lt;li&gt;速率上限 10 Mbps&lt;/li&gt;
&lt;li&gt;約有 40% 機率遺失封包、10% 機率損毀&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;根據定義可以計算：&lt;br&gt;
&lt;code&gt;(封包大小 1,500 bytes) * (單位轉換 8 bit / byte) * (成功率 60%) = 平均封包大小 7,200 bits&lt;/code&gt;&lt;br&gt;
&lt;code&gt;(速度 10 Mbps) / (封包 7,200 bits) = 每秒可傳送 1,388.88 個封包&lt;/code&gt;&lt;br&gt;
&lt;code&gt;1 / (每秒 1,388.88 封包) = 每封包間隔 0.72 毫秒&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;雖然理論值是這樣，不過因為 &lt;code&gt;tc-netem&lt;/code&gt; 實作的關係，似乎 0.75 毫秒才是最佳延遲，實驗及試算了好久都不知道怎麼得出正確數字。&lt;/p&gt;
&lt;!--
另外如果採用接收端定期回傳狀態的方式，可推算幾個搭配組合：  
`1 / (1/.75 - 1/.754) = 141.4 ms`  
`1 / (1/.75 - 1/.762) = 47.6 ms`  
`1 / (1/.75 - 1/.780) = 19.5 ms`

即為發送端以 0.754 毫秒間隔發送封包時，接收端可以用 142 毫秒間隔回傳狀態而不造成壅塞。  
同理，`(發送端間隔 0.762 ms, 接收端間隔 48 ms)` 及 `(發送端間隔 0.780 ms, 接收端間隔 20 ms)` 也是不錯的組合，可以視情況選擇當下最佳策略。
--&gt;
&lt;h1&gt;檔案壓縮   {#compress}&lt;/h1&gt;
&lt;p&gt;原先在 Discord 嘴砲說想直接用外部函式庫完成這次實驗，想說既然都讓老師把檔案亂度增加了，那應該是不需要玩壓縮的技巧。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/discord-compress.png&quot; alt=&quot;於 Discord 詢問使用壓縮函式庫&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;於 Discord 詢問使用壓縮函式庫&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;不過後來得知檔案內容只包含可視字元，轉換為 ASCII 是 &lt;code&gt;0x21&lt;/code&gt; 到 &lt;code&gt;0x7E&lt;/code&gt; 的區段，在每個 byte 中 256 種可能中只佔了 94 種。&lt;/p&gt;
&lt;p&gt;在此假設檔案亂度不低，也就是外部壓縮函式庫幫助有限，因此採用類似 &lt;code&gt;base64_decode()&lt;/code&gt; 的方式將檔案從可視字元區段映射到整個空間。&lt;/p&gt;
&lt;p&gt;最簡單的做法當然是取消最前面固定為 0 的位元，只要透過簡單的位元運算，就讓每 8 個可視字元字映射到 7 bytes，節省 12.5% 空間。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/conv-table.png&quot; alt=&quot;每 8 個可視字元可映射至 7 bytes&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;每 8 個可視字元可映射至 14 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;經過計算後，發現可以透過運算，把每 17 個可視字元映射到 14 bytes，省下了 17.6% 的空間。而運算過程中，剛好勉強低於 &lt;code&gt;__int128&lt;/code&gt; 的上限，實作起來不算複雜。&lt;/p&gt;
&lt;p&gt;如此讓每個封包 1,470 bytes 的內容實際可塞下 1,785 個可視字元，封包總數量減少到 9,500 個。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/compress-printable.png&quot; alt=&quot;把每 17 個可視字元映射到 14 bytes&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;把每 17 個可視字元映射到 14 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在最極端狀況下，每個封包其實可以塞下 1,794 個可視字元：&lt;br&gt;
&lt;code&gt;(log(256) / log(94)) * 1470 = 1794&lt;/code&gt;&lt;br&gt;
雖然可以省下 18.1% 的空間，不過實作起來會困難許多，因此沒有採用此方法。&lt;/p&gt;
&lt;h1&gt;減少多餘等待時間   {#speed-up}&lt;/h1&gt;
&lt;p&gt;在經過分析後，發現原本的程式最前面將檔案合併成大封包，再分割成 9,500 個區塊的過程中，大約會耗費 500 毫秒的時間，因此改為邊切割邊發送第一輪封包。&lt;/p&gt;
&lt;p&gt;而接收端如果在結束前才一次寫入，會耗費大約 350 毫秒的時間，發現後改為判斷接收完一個檔案就寫入一次。&lt;/p&gt;
&lt;p&gt;另外由於評測的機制是發送端結束後，會強制關閉接收端並開始比對檔案。因此發送端不能太快結束，但太晚結束又會影響表現。&lt;br&gt;
後來測試出接收端在剩下大約 5 - 10 個區塊未完成時，提前傳送關閉指令是較為折衷的作法。&lt;/p&gt;
&lt;h1&gt;動態調整發送間隔   {#dynamic-delay}&lt;/h1&gt;
&lt;p&gt;為了進一步最佳化性能，在接收端回傳狀態封包時，也順便帶上當下的時間戳。&lt;br&gt;
發送端可以用來計算單向的延遲，判斷緩衝區是否已被塞滿。&lt;/p&gt;
&lt;p&gt;原本有實作根據延遲時間自動調整間隔的功能，不過由於延遲是隨機在 50 - 150 毫秒之間飄動，事後證實效益不大。&lt;br&gt;
後來改為使用理論值來計算發送間隔，可以達到較穩定的效果。&lt;/p&gt;
&lt;h1&gt;沒用到 UDP 的玩法   {#no-udp}&lt;/h1&gt;
&lt;p&gt;從看到實驗限制後，就有想到或許可以透過指令列參數，利用側通道傳送資料，不過覺得做起來稍嫌麻煩，因此一直沒有動工。&lt;/p&gt;
&lt;p&gt;在正規作法進步到 13.08 秒，想不到可以怎麼繼續加速後，就決定來實作看看，完成後還真的得到比當時第一名還快 70 倍的破表分數。&lt;br&gt;
雖然有股想要壓到 0.02 秒以下的衝動，不過畢竟初衷只是確認可行性，還是決定先就此打住。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/cmdline-rank.png&quot; alt=&quot;當下計分板 0.18 秒成績&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;當下計分板 0.18 秒成績&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;評測方式   {#judge}&lt;/h2&gt;
&lt;p&gt;評測平台會建立 &lt;code&gt;/sender_dir/&lt;/code&gt; 及 &lt;code&gt;/receiver_dir/&lt;/code&gt; 兩個資料夾，並將發送端及接收端的執行檔分別置於 &lt;code&gt;/sender_dir/sender_bin&lt;/code&gt; 及 &lt;code&gt;/receiver_dir/receiver_bin&lt;/code&gt;。&lt;br&gt;
在 &lt;code&gt;/sender_dir/files/&lt;/code&gt; 資料夾放有 1,000 個隨機檔案，執行結束後會檢查是否成功傳輸至 &lt;code&gt;/receiver_dir/files/&lt;/code&gt; 資料夾。&lt;/p&gt;
&lt;p&gt;以發送端來說，先使用 &lt;code&gt;chroot(&amp;quot;/sender_dir/&amp;quot;)&lt;/code&gt; 防止執行環境存取外部檔案後，再執行 &lt;code&gt;/sender_bin --read-from=&amp;quot;/files&amp;quot; --send-to=&amp;quot;localhost:4242&amp;quot;&lt;/code&gt; 指令啟動。&lt;br&gt;
接收端則是以 &lt;code&gt;chroot(&amp;quot;/receiver_dir/&amp;quot;)&lt;/code&gt; 限制環境後，再執行 &lt;code&gt;/receiver_bin --listen-port=&amp;quot;4242&amp;quot; --store-to=&amp;quot;/files&amp;quot;&lt;/code&gt; 指令，將透過 UDP 協定收到的封包儲存至 &lt;code&gt;/receiver_dir/files/&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;本題是限制網路層的傳輸速度，應該有不少做法作法可以繞過，我只挑自己較為熟悉的一種來實作。&lt;/p&gt;
&lt;h2&gt;cmdline 簡介   {#cmdline}&lt;/h2&gt;
&lt;p&gt;我是從 2021 年 4 月在調研 ldapsearch 資安漏洞時，翻閱原始碼而接觸到這件事的，不過後來發現因為有盡最大努力側面修補，攻擊雖然可行但時間點需要抓得很精確，因此後續不了了之。&lt;br&gt;
知道 cmdline 這種玩法後一直覺得很酷，或許寫成一篇科普短文也還不錯，但這裡為了篇幅就只講重點。&lt;/p&gt;
&lt;p&gt;熟悉 Linux 的大家應該都用過 &lt;code&gt;ps aux&lt;/code&gt; 指令，但知道其中實作方式的人可能不多。&lt;br&gt;
在 Linux 系統根目錄底下有個特殊的 &lt;code&gt;/proc/&lt;/code&gt; 資料夾，存放核心（kernel）的相關資訊，而底下以程序編號（Process ID）命名的資料夾則存放各程序的狀態。&lt;br&gt;
例如 &lt;code&gt;/proc/[PID]/fd/&lt;/code&gt; 底下以數字命名的檔案，會連結（symbolic link）到程式開啟的各個檔案；而 &lt;code&gt;/proc/[PID]/cmdline&lt;/code&gt; 檔案則寫著被執行時的參數，以 &lt;code&gt;0x00 (NUL)&lt;/code&gt; 字元區隔。&lt;/p&gt;
&lt;p&gt;這個 cmdline 檔案雖然無法直接修改，但程式可以透過 &lt;code&gt;prctl()&lt;/code&gt;、&lt;code&gt;pthread_setname_np()&lt;/code&gt; 更動，或直接修改 &lt;code&gt;main()&lt;/code&gt; 函式收到的 &lt;code&gt;char *argv[]&lt;/code&gt; 內容也會反映在上面。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/ps-cmdline.png?&quot; alt=&quot;透過 cmdline 查看指令參數&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;透過 cmdline 查看指令參數&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;作法說明   {#side-channel}&lt;/h2&gt;
&lt;p&gt;在通常狀況下，&lt;code&gt;main()&lt;/code&gt; 收到的 &lt;code&gt;char *argv[]&lt;/code&gt; 長度也就幾十、至多幾百個字，如果要拿來傳資料顯然效率不足。&lt;br&gt;
這時可以透過上面提過的函式更動，不過在此為了簡單實作，採用之前學過的 &lt;code&gt;exec()&lt;/code&gt; 呼叫自己，並在 &lt;code&gt;argv[1]&lt;/code&gt; 傳遞一個很長很長的參數，目的是擴充 &lt;code&gt;cmdline&lt;/code&gt; 檔案大小，才塞得下整個檔案內容。&lt;/p&gt;
&lt;p&gt;在完成後就能自由運用 &lt;code&gt;argv[1]&lt;/code&gt; 參數了，開始每隔 0.1 毫秒更新一次 &lt;code&gt;argv[1]&lt;/code&gt;，依序將檔案內容放上。這會同步到 &lt;code&gt;/proc/[PID]/cmdline&lt;/code&gt;，也就是 &lt;code&gt;ps aux&lt;/code&gt; 指令會看到的結果。&lt;/p&gt;
&lt;p&gt;而接收端則是先等候一小段時間，先確保傳送端已啟動後，持續檢查位於 &lt;code&gt;/proc/[PID]/cmdline&lt;/code&gt; 檔案的參數內容，如果有異動就寫入 &lt;code&gt;/receiver_bin/files/[ID]&lt;/code&gt; 目標檔案。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/12/argv-cmdline.png&quot; alt=&quot;使用 argv / cmdline 繞過限制傳送&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;使用 argv / cmdline 繞過限制傳送&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;使用這個方法，理論上可以再 &lt;code&gt;fork()&lt;/code&gt; 出不同程序（process）同步執行，用到本題上限的 15 個程序可以加速不少。&lt;/p&gt;
&lt;p&gt;也可以把間隔時間依照檔案大小自動調整，或是讓接收端發出訊號，減少不必要的等待時間。&lt;/p&gt;
&lt;h1&gt;後記   {#epilogue}&lt;/h1&gt;
&lt;p&gt;寫這個實驗的過程中，心中一直被「執行效能」的想法所侷限，但仔細思考後認知到在這個場景下，最珍貴的資源是網路而不是 CPU 效能，有許多顯然花費不合理運算的事情實際上卻可以增進執行效率。&lt;/p&gt;
&lt;p&gt;老師在隔週的課堂也說了，原先沒想到大家會把時間用在最佳化上面，因此乾脆將一堂實驗課讓出來，給同學們分享各自作法的機會。&lt;br&gt;
雖然有做好 &lt;a href=&quot;https://hackmd.io/@Sean64/netprog-udp&quot;&gt;簡報&lt;/a&gt;，
不過由於剛好要 &lt;a href=&quot;/2022/01/ceh&quot;&gt;參與資安檢測&lt;/a&gt;，
當周課堂無法出席報告，經過老師同意只好以 &lt;a href=&quot;https://youtu.be/fY5yiRY0N6k&quot;&gt;預錄影片&lt;/a&gt; 代替。&lt;/p&gt;
&lt;p&gt;感謝 &lt;a href=&quot;https://thect.cc/&quot;&gt;Thect&lt;/a&gt;、
&lt;a href=&quot;https://imych.one/&quot;&gt;yc油成&lt;/a&gt;、
&lt;a href=&quot;https://jerry.tw/&quot;&gt;Jerry Hsu&lt;/a&gt;、
&lt;a href=&quot;https://github.com/andy89923&quot;&gt;CTFang&lt;/a&gt;、
&lt;a href=&quot;https://siriuskoan.one/&quot;&gt;Sirius Koan&lt;/a&gt;、
&lt;a href=&quot;https://blog.twinklestar03.com/&quot;&gt;TwinkleStar03&lt;/a&gt;
等朋友協助審閱文章提供建議，指出盲點讓文意更通順。&lt;br&gt;
對於文章有任何想法，都歡迎來 &lt;a href=&quot;https://twitter.com/Sea_n64/status/1603240158937387008&quot;&gt;Twitter&lt;/a&gt;、
&lt;a href=&quot;https://facebook.com/Sean0604/posts/3366877213584114&quot;&gt;Facebook&lt;/a&gt;
留言交流，或是在課堂實體捕捉我。&lt;/p&gt;
&lt;p&gt;如果想嘗試的朋友，老師也在課後將 &lt;a href=&quot;https://zoolab-org.github.io/lab_robust_udp/&quot;&gt;實驗題目規格&lt;/a&gt; 公開，歡迎參考練習。&lt;/p&gt;
&lt;style&gt;
.post table td {
    color: #666;
}

.post table td a {
    color: #6bf;
}

.post table td a:hover,
.post table td a:active,
.post table td a:focus {
    color: #8cf;
}
&lt;/style&gt;</content:encoded>
    </item>
    <item>
      <title>交大資工所 推甄紀錄 韋詠祥</title>
      <pubDate>Sun, 27 Nov 2022 09:00:00 +0000</pubDate>
      <description>今年申請交大資工的丙丁組，皆在資料審查階段就獲得直接錄取，目前已於丁組系計中報到。</description>
      <link>https://blog.sean.taipei/2022/11/nctu</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2022/11/nctu</guid>
      <content:encoded>&lt;h1&gt;TL;DR   {#tldr}&lt;/h1&gt;
&lt;p&gt;今年申請交大資工的丙組、丁組，由於時程因素，只做了下圖 2 頁的自傳 + 讀書計畫：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;a href=&quot;https://img.sean.taipei/2022/11/nctu.pdf&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/nctu.png&quot; alt=&quot;韋詠祥 交大資工所 推甄自傳 縮圖&quot;&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;交大資工所 推甄自傳&lt;br&gt;&lt;a href=&quot;https://img.sean.taipei/2022/11/nctu.pdf&quot;&gt;https://img.sean.taipei/2022/11/nctu.pdf&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;丙丁組皆在資料審查階段就獲得直接錄取，目前已於丁組（系計中）報到。&lt;/p&gt;
&lt;h1&gt;為何只投交大   {#why-nctu}&lt;/h1&gt;
&lt;p&gt;對部分資工系學生而言，研究所的順位或許是國外 &amp;gt; 台大 &amp;gt; 交清 &amp;gt; 其他學校，但在我的觀點中並非如此。&lt;/p&gt;
&lt;p&gt;由於想留在台灣，現階段較不考慮出國攻讀研究所。&lt;br&gt;
某些人會宣稱台大資源比交大豐富，但在資訊安全及實作領域，交大或許勝過台大。&lt;br&gt;
有朋友同時申請交大及清大，但兩者錄取的門檻差不多，如果都上了我只會選交大，因此就不去佔名額浪費資源了。&lt;/p&gt;
&lt;p&gt;而且與交大相關領域的教授都相對熟識，直升對我而言是個最好的選擇。&lt;br&gt;
因此在我心中順位是 交大 &amp;gt; 台大 &amp;gt; 清大 &amp;gt; 國外研究所。&lt;/p&gt;
&lt;h1&gt;交大資工 研究所組別簡介   {#nctu-cs}&lt;/h1&gt;
&lt;p&gt;交大資工共分為 4 個所，分別是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;資科工所（資訊科學與工程研究所）&lt;/li&gt;
&lt;li&gt;網工所（網路工程研究所）/ 推甄收 30 人&lt;/li&gt;
&lt;li&gt;多媒所（多媒體工程研究所）/ 推甄收 27 人&lt;/li&gt;
&lt;li&gt;數據所（數據科學與工程研究所）/ 推甄收 34 人&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中資科工所又再分為 4 個組：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;甲組 / 推甄收 87 人&lt;/li&gt;
&lt;li&gt;丙組（實作導向）/ 推甄收 15 人&lt;/li&gt;
&lt;li&gt;丁組（系統與網路管理實務，系計中）/ 推甄收 6 人&lt;/li&gt;
&lt;li&gt;戊組（校務資訊系統技術與實務，校計中）/ 推甄收 7 人&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外資訊學院底下，還有個資安學程（資通安全碩士學位學程），前稱資電亥客。&lt;/p&gt;
&lt;p&gt;各組別之間主要差異是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以找的 &lt;a href=&quot;https://www.cs.nycu.edu.tw/education/master/advisor&quot;&gt;教授名單&lt;/a&gt; 不同、名額分開計算&lt;/li&gt;
&lt;li&gt;畢業標準、必修課程不同&lt;/li&gt;
&lt;li&gt;審查注重的面向不同&lt;/li&gt;
&lt;li&gt;丙丁戊組通過初步書審後，需個別面試&lt;/li&gt;
&lt;li&gt;丁組需負責開發資工系服務、戊組需協助維護交大校務系統&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;申請過程   {#journal}&lt;/h1&gt;
&lt;p&gt;通常比較認真的學生都會提前半年一年開始準備，而我雖然一直把這件事放在待辦清單，但由於出現其他更重要的事務，拖到最後一刻才處理。&lt;/p&gt;
&lt;p&gt;上了大學之後，雖然持續有在參加各領域活動，但沒有動機整理自身經歷，連獎狀都是散落在三四個不同地方。&lt;br&gt;
九月剛 &lt;a href=&quot;/2022/09/icann-zh&quot;&gt;出國參與 ICANN 會議&lt;/a&gt; 回來，10/6（四）又受邀擔任座談會與談人，因此 10/7（五）才開始準備資料，共有 5 天可以處理。&lt;/p&gt;
&lt;p&gt;第一天 10/7（五）先去行事曆、信箱、雲端硬碟到處翻，回顧大學階段做了哪些事，並將主要的經歷放上網站。&lt;br&gt;
個人網站的部分，從國中之後就沒什麼動過了，趁這次機會跟 &lt;a href=&quot;https://imych.one/&quot;&gt;@yc97463&lt;/a&gt; 借用版面設計來更新。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/sean-2016.png&quot; alt=&quot;最初的模樣&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/sean-2022.png&quot; alt=&quot;修改前&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/sean-now.png&quot; alt=&quot;更新後&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;最初的模樣（&lt;a href=&quot;https://web.archive.org/web/20160412001622/https://sean.taipei/&quot;&gt;2016 年&lt;/a&gt;）&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;修改前（&lt;a href=&quot;https://web.archive.org/web/20220923135224/https://www.sean.taipei/&quot;&gt;2022 年&lt;/a&gt;）&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;更新後（&lt;a href=&quot;https://web.archive.org/web/20221118044803/https://www.sean.taipei/&quot;&gt;現在&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;第二天 10/8（六）開始研究推甄相關規則、需求，並初步填寫系統上的資料。&lt;/p&gt;
&lt;p&gt;第三天 10/9（日）製作自傳、讀書計畫時，由於知道教授們時間寶貴，決定這次將審查資料濃縮在 2 頁 PDF 內解決。&lt;/p&gt;
&lt;p&gt;對於版面設計不在行的我，突然想到平常用的 Markdown 很符合資工人的日常，或許可以在維持可讀性的同時又增添一點設計感，因此用 macOS 內建的 Pages 手刻出相似樣式。&lt;/p&gt;
&lt;p&gt;完成自傳草稿後，也寄信給四位師長，詢問是否願意協助撰寫推薦函。&lt;br&gt;
雖然覺得資料不齊全就開口詢問老師們有點不尊重，但礙於時程不先給出半成品也不是辦法，只能各處都先做到基本分再求精進。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/nctu-letter-ask.jpg&quot; alt=&quot;詢問教授撰寫推薦函&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;詢問教授撰寫推薦函&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;第四天 10/10（一）國慶連假，先研究了推薦函如何填覆、有哪些欄位，整理時程資訊，再翻找信件往來紀錄、聊天記錄，列出與推薦人相關的事件供四位推薦人參考。&lt;/p&gt;
&lt;p&gt;這次推薦人找了兩位交大資工系上的老師、一位科法所的老師、一位網路治理及安全領域德高望重的前輩。&lt;br&gt;
很感激四位師長願意用自己寶貴的時間，替我撰寫推薦函、為我的能力背書。&lt;/p&gt;
&lt;p&gt;第五天 10/11（二）17:00 報名截止，去投幣列印了歷年成績單，整理申請表將報名資料繳交至教務處。&lt;br&gt;
由於時間不足，系統上競賽成績、開發經驗、其他有利資料等欄位都只能留空。&lt;/p&gt;
&lt;h1&gt;填覆資料   {#application}&lt;/h1&gt;
&lt;p&gt;交大資工所的招生申請系統中，共有 50+ 個欄位需要填寫，以下是本次主要欄位資料。&lt;/p&gt;
&lt;h2&gt;總名次及修業學分   {#application-rank}&lt;/h2&gt;
&lt;p&gt;歷年平均：81.3 分&lt;br&gt;
系排名：62%（123 名 / 共 199 人）&lt;br&gt;
已修習：136 學分（6 學期平均 23 學分）&lt;br&gt;
不及格：12 學分（微積分 4 學分 * 3 門）&lt;/p&gt;
&lt;h2&gt;修課狀況自評   {#application-overview}&lt;/h2&gt;
&lt;p&gt;總體而言數學及英文科目分數較差，而資訊科目應對起來較為輕鬆，尤其實務導向課程表現較為亮眼。&lt;/p&gt;
&lt;p&gt;由於同時忙於系計中、資訊社群、資安競賽、開源貢獻、網路治理等領域，無法兼顧成績表現，僅能維持平均水準。&lt;/p&gt;
&lt;h2&gt;修習電資領域專業課程「最佳」表現   {#application-best}&lt;/h2&gt;
&lt;p&gt;計算機系統管理：95 分&lt;br&gt;
計算機網路管理：99 分&lt;br&gt;
網路規劃與管理實務：99 分&lt;br&gt;
演算法概論：94 分&lt;br&gt;
（研）全球網路治理：95 分&lt;br&gt;
組合語言與系統程式：97 分&lt;/p&gt;
&lt;p&gt;其中 NA、SA、組語為大一修習。&lt;/p&gt;
&lt;h2&gt;修習電資領域專業課程「最差」表現   {#application-worst}&lt;/h2&gt;
&lt;p&gt;線性代數：75 分&lt;br&gt;
機率：67 分&lt;br&gt;
密碼學概論：69 分&lt;br&gt;
計算機組織：75 分&lt;br&gt;
（研）程式安全：71 分&lt;/p&gt;
&lt;p&gt;數學佔比高的科目表現較差，僅能滿足基本需求。
部分資工課程於期末時因外務繁忙而難以兼顧成績。&lt;/p&gt;
&lt;h1&gt;申請結果   {#result}&lt;/h1&gt;
&lt;p&gt;這次我只申請丙組、丁組，皆由於第一階段書面審查分數較高，教授們決議跳過面試提供逕取（直接錄取）資格。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/score-201.png&quot; alt=&quot;丙組成績單&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/score-202.png&quot; alt=&quot;丁組成績單&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/nctu-result.jpg&quot; alt=&quot;丙組丁組皆得到直接錄取&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;丙組成績單&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;丁組成績單&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;兩組皆得到直接錄取&lt;br&gt;（來源：&lt;a href=&quot;https://exam.nycu.edu.tw/bulletin2.aspx?id=14048c8a-d1ca-465d-a603-1b5795e1f1da&amp;amp;id2=930cd74c-95ed-45bb-980f-f636b42230eb&quot;&gt;交大碩班推甄榜單&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;目前已完成丁組報到，並放棄丙組資格讓其他考生得以儘速遞補，畢業後碩班將繼續留在系計中服務。&lt;/p&gt;
&lt;h1&gt;後記   {#epilogue}&lt;/h1&gt;
&lt;p&gt;幾年前聽到丁組的名聲其實不太好，甚至聽過有人比喻為用勞力換學歷，某些人為了畢業不是很順利。&lt;/p&gt;
&lt;p&gt;但從我加入系計中兩年多來，有許多事物漸漸在改變，也有愈來愈多人才加入丁組，整體氣氛相當融洽。&lt;br&gt;
甚至去年 &lt;a href=&quot;https://www.libralight.dev/&quot;&gt;Leo Chen&lt;/a&gt; 及 &lt;a href=&quot;https://xdavidwu.link/about/&quot;&gt;David Wu&lt;/a&gt; 兩位系上技術頂尖的強者從大學時就在系計中服務，畢業後也以丁組作為第一志願，讓我在審慎思考過後決定留在丁組繼續與大家打拼。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/cc-sitcon.jpg&quot; alt=&quot;同學自發於 SITCON 閃電秀分享&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/11/cc-gmaps.jpg&quot; alt=&quot;助教休息空間鯊滿為患&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;同學自發於 SITCON 閃電秀分享&lt;br&gt;（圖源：&lt;a href=&quot;https://www.flickr.com/photos/sitcon/52366050249/in/album-72177720302195888/&quot;&gt;SITCON Flickr&lt;/a&gt;）&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;助教休息空間鯊滿為患&lt;br&gt;（圖源：&lt;a href=&quot;https://goo.gl/maps/Q4TsM1G1Vh67zzhu8&quot;&gt;Google Maps&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;本文同步分享於 &lt;a href=&quot;https://t.me/SeanChannel/107&quot;&gt;Telegram&lt;/a&gt;、
&lt;a href=&quot;https://twitter.com/Sea_n64/status/1596804193339158529&quot;&gt;Twitter&lt;/a&gt;、
&lt;a href=&quot;https://www.facebook.com/Sean0604/posts/3350524638552705&quot;&gt;Facebook&lt;/a&gt;，
礙於文章篇幅，如果有什麼好奇的、想暸解更多的點，都歡迎來留言區交流。&lt;/p&gt;
&lt;h1&gt;參考連結   {#reference}&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://coder.tw/?p=7761&quot;&gt;丁組推甄心得 + QA&lt;/a&gt;（2021 年 9 月）&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://it.cs.nycu.edu.tw/join-us&quot;&gt;交大資工系計中 加入我們&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tg.pe/lv5in&quot;&gt;丁戊組推甄心得 + 考古題&lt;/a&gt;（2021 年 9 月）&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ptt.cc/bbs/graduate/M.1585660982.A.56F.html&quot;&gt;丁戊組推甄心得&lt;/a&gt;（2020 年 3 月）&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.sean.taipei/2019/08/nctu&quot;&gt;大學個人申請 備審資料擴散紀錄&lt;/a&gt;（2019 年 8 月）&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
.post h2 {
    margin: -6px 0 4px 0;
}

.post table td {
    color: #666;
}

.post table td a {
    color: #6bf;
}

.post table td a:hover,
.post table td a:active,
.post table td a:focus {
    color: #8cf;
}
&lt;/style&gt;</content:encoded>
    </item>
    <item>
      <title>ICANN75 - 吉隆坡之旅</title>
      <pubDate>Fri, 23 Sep 2022 12:10:00 +0000</pubDate>
      <description>很高興這次能獲得 NII 的全額補助，出國參與 ICANN75 會議，並獲得知識及友情上滿滿的收穫。</description>
      <link>https://blog.sean.taipei/2022/09/icann-zh</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2022/09/icann-zh</guid>
      <content:encoded>&lt;p&gt;很高興這次能在 NII 舉辦的「ICANN 公共政策研習營」獲選為優良學員，受邀參與位於馬來西亞吉隆坡的 ICANN75 年度會議，並提供旅費補助。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There's also a &lt;a href=&quot;https://blog.sean.taipei/2022/09/icann-en&quot;&gt;English version&lt;/a&gt; of this post.&lt;/p&gt;
&lt;h1&gt;前情提要&lt;/h1&gt;
&lt;p&gt;ICANN 是統籌分配管理全球 IP 位址及網域名稱的非營利組織，內部分為多個 Stackholder Group（利害關係人團體），由下而上的討論制定政策&lt;/p&gt;
&lt;p&gt;在台灣由 NII 每年舉辦兩場研習營，只要全程參與就能拿到數千元的獎學金，並且每年選出幾位優秀學員參與 APrIGF 及 ICANN 等國際會議。&lt;/p&gt;
&lt;p&gt;一個是 &lt;a href=&quot;https://igcamp.tw/&quot;&gt;網路治理研習營&lt;/a&gt;，分為網路安全、平台規範、數位人權三組，探討多個相關議題。&lt;br&gt;
今年我被邀請於閉幕時 &lt;a href=&quot;https://hackmd.io/@Sean64/igcamp-2022&quot;&gt;分享參與經驗&lt;/a&gt;，並獲選為優良實習學員，以中文撰寫 &lt;a href=&quot;https://igwatch.tw/2022/07/29/%E2&quot;&gt;三篇&lt;/a&gt; &lt;a href=&quot;https://igwatch.tw/2022/08/08/%E2&quot;&gt;會議&lt;/a&gt; &lt;a href=&quot;https://igwatch.tw/2022/08/23/%E8&quot;&gt;摘要&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;另一個則是 &lt;a href=&quot;https://dnslearn.tw/icanncamp-home&quot;&gt;ICANN 公共政策研習營&lt;/a&gt;，透過扮演 GAC 政府代表、ALAC 群眾代表、GNSO 網域代表，針對頂級域名相關議題，分組討論組內的觀點，再於模擬會議上凝聚全體共識。&lt;br&gt;
這次我順利獲選為優秀學員，並得到旅費、住宿、防疫旅館、生活費等全額補助，前往吉隆坡參與 ICANN75 大會。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-twcamp-discuss.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-twcamp-group.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;分為各個 Stackholder Group 討論&lt;/td&gt;
&lt;td&gt;ICANN 公共政策研習營合照&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;旅程規劃&lt;/h1&gt;
&lt;p&gt;由於 NII 核銷規定，只能訂購指定日期的航班，無法自費在當地多留個幾天。&lt;br&gt;
再加上來回確認延誤了訂購時程，只剩沒多少航班可供挑選了。&lt;/p&gt;
&lt;p&gt;因此我選擇在週六晚上到新加坡轉機，隔天早上再飛馬來西亞。也因為這個晚上轉機的時間，讓我能參訪新加坡樟宜國際機場的多處美景。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-sgp.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-badge.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;晚上逛新加坡樟宜國際機場&lt;/td&gt;
&lt;td&gt;順利報到，取得 ICANN75 名牌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;接著週一、週二、週三，整天都在參加 ICANN75 會議，其中有 6 個場次是合約中指定的，剩下的讓我自由挑選。&lt;/p&gt;
&lt;p&gt;回程航班訂在週四下午，也因此無緣參與最後一天的 Public Forum 等議程。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-apralo.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-apac-room.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;參與 ICANN75 APRALO 議程&lt;br&gt;（圖源：&lt;a href=&quot;https://www.flickr.com/photos/icann/52371358028/in/album-72177720302230206/&quot;&gt;ICANN Flickr&lt;/a&gt;）&lt;/td&gt;
&lt;td&gt;參與 ICANN75 APAC Space 議程&lt;br&gt;（圖源：&lt;a href=&quot;https://twitter.com/ICANN/status/1572143906497921024/&quot;&gt;ICANN Twitter&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;認識新朋友&lt;/h1&gt;
&lt;p&gt;第一天抵達 KLCC（吉隆坡會議中心，Kuala Lumpur Convention Centre）時，NII 的理旋跟我說可以去參與 NextGen 議程，認識一下與我同年的小朋友們。&lt;/p&gt;
&lt;p&gt;在 ICANN75 會場遇到的所有人都相當的友善，我只是靠近聽他們在聊些什麼，就直接叫我名字（應該是看名牌）跟我打招呼，並歡迎我加入對話。&lt;/p&gt;
&lt;p&gt;前兩天由於時間因素，沒能跟 NextGen 計劃的夥伴們一起吃晚餐，讓我覺得非常失落。&lt;/p&gt;
&lt;p&gt;而在週三晚上，我們約去中國城逛街，再到 Jalan Alor 美食街一起吃泰式料理。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-china.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-dinner.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;吉隆坡中國城&lt;/td&gt;
&lt;td&gt;共享泰式料理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我們 5 人之中，沒有人的母語是英文，但他們都非常包容我一直打結的英文。&lt;/p&gt;
&lt;p&gt;來自馬來西亞的 Adlin 送了在地的精品巧克力、&lt;br&gt;
來自柬埔寨 Somaly 送了我吳哥窟鑰匙圈、&lt;br&gt;
Phyo 送我緬甸當地的糖果。&lt;/p&gt;
&lt;p&gt;沒想到在 ICANN 會議期間會認識到這麼多好朋友，我很後悔沒有準備任何台灣紀念品。（甚至出國前把所有新台幣都換成了馬來西亞令吉）&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-adlin.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-somaly.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;來自馬來西亞的 Adlin&lt;/td&gt;
&lt;td&gt;來自柬埔寨的 Somaly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;結語&lt;/h1&gt;
&lt;p&gt;我真的很榮幸能有機會去吉隆坡與來自各地的朋友交流，未來將繼續深入研究 ICANN 政策及網路治理，希望有天能成為 ICANN Fellow，再次見到令我感動的大家。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-group-afternoon.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-apac-group.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;點心休息時間&lt;/td&gt;
&lt;td&gt;APAC 團體照&lt;br&gt;（圖源：&lt;a href=&quot;https://www.flickr.com/photos/icann/52373019221/in/album-72177720302230206/&quot;&gt;ICANN Flickr&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;本文同步分享於 &lt;a href=&quot;https://www.facebook.com/Sean0604/posts/3292442171027619&quot;&gt;Facebook&lt;/a&gt;，
如果有什麼想法，都歡迎來留言區交流。&lt;/p&gt;
&lt;h1&gt;相關連結&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;本文 &lt;a href=&quot;https://blog.sean.taipei/2022/09/icann-en&quot;&gt;英文版&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://75.schedule.icann.org/agenda&quot;&gt;ICANN75 議程表&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ICANN 官方 &lt;a href=&quot;https://www.flickr.com/photos/icann/albums&quot;&gt;Flickr 相簿&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.twnic.tw/mps/page10.html&quot;&gt;ICANN 多方利害關係人模式&lt;/a&gt;（TWNIC 中文版介紹）&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
.post table td {
    color: #666;
}

.post table td a {
    color: #6bf;
}

.post table td a:hover,
.post table td a:active,
.post table td a:focus {
    color: #8cf;
}
&lt;/style&gt;</content:encoded>
    </item>
    <item>
      <title>ICANN75 - Trip to Kuala Lumpur</title>
      <pubDate>Fri, 23 Sep 2022 12:00:00 +0000</pubDate>
      <description>I'm glad that I can attend the ICANN75 Meeting with NII financial aid and meet so many nice friends.</description>
      <link>https://blog.sean.taipei/2022/09/icann-en</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2022/09/icann-en</guid>
      <content:encoded>&lt;p&gt;I'm glad that I got the opportunity to be selected by NII program to attend the ICANN75 Annual General Meeting in Kuala Lumpur, Malaysia.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There's also a &lt;a href=&quot;https://blog.sean.taipei/2022/09/icann-zh&quot;&gt;Mandarin version&lt;/a&gt; for my Taiwanese friends.&lt;br&gt;
這篇文是寫給在吉隆坡認識的好朋友們，歡迎台灣朋友左轉 &lt;a href=&quot;https://blog.sean.taipei/2022/09/icann-zh&quot;&gt;中文版&lt;/a&gt; 文章。&lt;/p&gt;
&lt;h1&gt;Why I can attend ICANN75&lt;/h1&gt;
&lt;p&gt;NII hosts two study camps in Taiwan every year. It provides scholarships for all attendees who finished the course, and selects a few students to attend international conferences like APrIGF and ICANN meetings.&lt;/p&gt;
&lt;p&gt;The first one is called &lt;a href=&quot;https://igcamp.tw/&quot;&gt;Internet Governance Camp&lt;/a&gt;, in which we discuss various issues. This year I was selected as a Intern Student, and had written &lt;a href=&quot;https://igwatch.tw/2022/07/29/%E2&quot;&gt;three&lt;/a&gt; &lt;a href=&quot;https://igwatch.tw/2022/08/08/%E2&quot;&gt;meeting&lt;/a&gt; &lt;a href=&quot;https://igwatch.tw/2022/08/23/%E8&quot;&gt;summaries&lt;/a&gt; in Mandarin.&lt;/p&gt;
&lt;p&gt;Another is &lt;a href=&quot;https://dnslearn.tw/icanncamp-home&quot;&gt;ICANN Public Policy Camp&lt;/a&gt;, I was rated as one of the best students during a simulation meeting about closed generic TLD, which provides the financial aid to attend ICANN75 and the chance to make friends here.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-twcamp-discuss.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-twcamp-group.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Discussing as Stackholder Groups&lt;/td&gt;
&lt;td&gt;ICANN Camp in Taiwan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;Flight Schedule&lt;/h1&gt;
&lt;p&gt;I have to arrive and depart on a specific date limited by the NII contract, which means that I cannot stay longer in Malaysia at my own expense.&lt;br&gt;
Also since I booked my ticket too late, there are not a lot of options to choose from.&lt;/p&gt;
&lt;p&gt;I flew from Taiwan to Singapore on Saturday evening, stayed the night at Singapore airport, then flew to Malaysia on Sunday morning.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-sgp.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-badge.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stay at Singapore Changi airport&lt;/td&gt;
&lt;td&gt;Got my ICANN75 badge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I attended the ICANN75 session from Monday to Wednesday. This scholarship program has specified 6 mandatory sessions to attend, and the rest is up to me.&lt;/p&gt;
&lt;p&gt;My return flight to Taiwan is on Thursday afternoon, so I don't have the chance to attend the last day of ICANN75 such as Public Forum.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-apralo.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-apac-room.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Attending ICANN75 APRALO session&lt;br&gt;(Source: &lt;a href=&quot;https://www.flickr.com/photos/icann/52371358028/in/album-72177720302230206/&quot;&gt;ICANN Flickr&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Attending ICANN75 APAC Space session&lt;br&gt;(Source: &lt;a href=&quot;https://twitter.com/ICANN/status/1572143906497921024/&quot;&gt;ICANN Twitter&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;Friends&lt;/h1&gt;
&lt;p&gt;The first day I arrived at KLCC (Kuala Lumpur Convention Centre), Sophie from NII told me I can make some friends from NextGen, those who are at the same age as me.&lt;/p&gt;
&lt;p&gt;All people at ICANN75 meeting are so kind. When I approach them and listen to what they are talking about, most people will call my name (on the badge) and greet with me.&lt;/p&gt;
&lt;p&gt;But sadly, I missed their invitations for dinner for the first two nights. It's a shame that I couldn't spend more time with them.&lt;/p&gt;
&lt;p&gt;The Wednesday night, we went to chinatown for shopping and having Thai food at Jalan Alor Food Street together.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-china.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-dinner.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;China Town&lt;/td&gt;
&lt;td&gt;Thai food&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;None of us speaks English as our native language, but they are all so inclusive for my unclear accent.&lt;/p&gt;
&lt;p&gt;Adlin from Malaysia gave me local refined Chocolate.&lt;br&gt;
Somaly gave me Angkor Wat keychain from Cambodia.&lt;br&gt;
Phyo gave me some Myanmar candies.&lt;/p&gt;
&lt;p&gt;I didn't expect that I would make so many nice friends during ICANN meeting, I'm very regretful that I didn't prepare any Taiwanese souvenirs. (I even exchanged all Taiwan dollar to Malaysia Ringgits)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-adlin.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-somaly.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Adlin from Malaysia&lt;/td&gt;
&lt;td&gt;Somaly from Cambodia&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;Ending&lt;/h1&gt;
&lt;p&gt;I'm really glad to be here and have the chance to talk with different people. I'll keep digging into ICANN Policy and Internet Governance. And hope I can be ICANN fellow one day, to meet all the nice people again.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-group-afternoon.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src=&quot;https://img.sean.taipei/2022/09/icann-apac-group.jpg&quot; alt=&quot;&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Our tea break&lt;/td&gt;
&lt;td&gt;APAC Group Photo&lt;br&gt;(Source: &lt;a href=&quot;https://www.flickr.com/photos/icann/52373019221/in/album-72177720302230206/&quot;&gt;ICANN Flickr&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;Links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.sean.taipei/2022/09/icann-zh&quot;&gt;Mandarin Version&lt;/a&gt; of this post&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://75.schedule.icann.org/agenda&quot;&gt;ICANN75 Agenda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ICANN &lt;a href=&quot;https://www.flickr.com/photos/icann/albums&quot;&gt;Flickr Album&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
.post table td {
    color: #666;
}

.post table td a {
    color: #6bf;
}

.post table td a:hover,
.post table td a:active,
.post table td a:focus {
    color: #8cf;
}
&lt;/style&gt;</content:encoded>
    </item>
    <item>
      <title>Kubernetes 網站貢獻心得</title>
      <pubDate>Fri, 05 Aug 2022 10:00:00 +0000</pubDate>
      <description>成為了 Kubernetes 網站中文語系的 Approver，簡單整理了 Kubernetes 社群的貢獻流程、相關身份。</description>
      <link>https://blog.sean.taipei/2022/08/kubernetes</link>
      <guid isPermaLink="true">https://blog.sean.taipei/2022/08/kubernetes</guid>
      <content:encoded>&lt;h1&gt;前言   {#prologue}&lt;/h1&gt;
&lt;p&gt;今年 4 月時，在讀文件的過程中發現了個小錯字，發 PR 後看到 Kubernetes GitHub 的完整流程覺得很酷，就開始參與社群、持續貢獻到現在了。&lt;/p&gt;
&lt;p&gt;在研讀完幾份貢獻者說明文件、實際參與過數百個 PR 後，來寫篇中文筆記介紹整套制度流程。&lt;/p&gt;
&lt;p&gt;本文將先快速帶過發 PR 後到 merge 經過的階段，接著解釋 &lt;a href=&quot;#labels&quot;&gt;標籤的意義&lt;/a&gt;，最後統整 &lt;a href=&quot;#roles&quot;&gt;社群成員身份&lt;/a&gt; 及晉升流程。&lt;/p&gt;
&lt;h1&gt;發起 Pull Request 後會發生哪些事   {#after-pr}&lt;/h1&gt;
&lt;p&gt;在 Kubernetes 的專案中，大多是由 &lt;code&gt;@k8s-ci-robot&lt;/code&gt; 負責各項自動化任務的，先來講講行為流程。&lt;/p&gt;
&lt;p&gt;在出現新的 Pull Request 時，根據改動的檔案加上不同標籤，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 k/website 專案中，自動加上 &lt;kbd&gt;sig/docs&lt;/kbd&gt;&lt;/li&gt;
&lt;li&gt;如果更動的行數在 30 - 99 行，標示為 &lt;kbd&gt;size/M&lt;/kbd&gt;&lt;/li&gt;
&lt;li&gt;依照檔案所在的資料夾，加上語言 &lt;kbd&gt;language/zh&lt;/kbd&gt; 標籤&lt;/li&gt;
&lt;li&gt;如果使用者有乖乖簽署貢獻者授權協議，加上必備的 &lt;kbd&gt;cncf-cla: yes&lt;/kbd&gt; 標籤&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在加上標籤後，根據修改到的檔案隨機指派兩名 Reviewer，並告訴使用者在收到 &lt;kbd&gt;lgtm&lt;/kbd&gt; 後該找哪位 Approver 協助。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-bot.jpg&quot; alt=&quot;@k8s-ci-robot 為 PR 加上 label 分類&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;&lt;code&gt;@k8s-ci-robot&lt;/code&gt; 為 PR 加上 label 分類（&lt;a href=&quot;https://github.com/kubernetes/website/pull/35700&quot;&gt;k/website#35700&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;過 10 分鐘後，輪到為每個 PR 建置預覽網站的 Netlify 機器人出場了，會留言告訴我們測試站的連結、失敗的話錯誤原因是什麼。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-netlify.jpg&quot; alt=&quot;Netlify 機器人產生好預覽網站&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;Netlify 機器人產生好預覽網站（&lt;a href=&quot;https://github.com/kubernetes/website/pull/35700&quot;&gt;k/website#35700&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;再來只要等搜集到 &lt;kbd&gt;lgtm&lt;/kbd&gt; + &lt;kbd&gt;approved&lt;/kbd&gt; 兩個標籤，並且沒有 &lt;kbd&gt;do-not-merge/hold&lt;/kbd&gt;、&lt;kbd&gt;needs-rebase&lt;/kbd&gt; 等負面標籤，就會被放進 Merge pool 中。&lt;/p&gt;
&lt;p&gt;在 Merge pool 中，為了避免衝突需要等待幾秒到幾分鐘的時間，排到隊後就會自動合併進去啦！&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-merge.jpg&quot; alt=&quot;得到 lgtm 及 approved 後自動被合併&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;得到 lgtm 及 approved 後自動被合併（&lt;a href=&quot;https://github.com/kubernetes/website/pull/34311&quot;&gt;k/website#34311&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;標籤的意義   {#labels}&lt;/h1&gt;
&lt;p&gt;前面快速帶過了整個 Pull Request 從發起到成功合併的流程，再來介紹一下數百個標籤中比較常用的幾個。&lt;/p&gt;
&lt;h2&gt;正向標籤   {#positive-labels}&lt;/h2&gt;
&lt;p&gt;&lt;kbd&gt;lgtm&lt;/kbd&gt;，即 Looks good to me 的意思，任何 Kubernetes 組織成員都可以使用 &lt;code&gt;/lgtm&lt;/code&gt; 指令加上此標籤。&lt;/p&gt;
&lt;p&gt;LGTM 標籤的意義是「這份程式碼改動看起來不錯」，因此只要檔案有更動，這個標籤就會消失，需要重新用 &lt;code&gt;/lgtm&lt;/code&gt; 指令加回來。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-lgtm.jpg&quot; alt=&quot;得到 lgtm 標籤後更動檔案&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;得到 lgtm 標籤後更動檔案（&lt;a href=&quot;https://github.com/kubernetes/website/pull/35411&quot;&gt;k/website#35411&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;kbd&gt;approved&lt;/kbd&gt;，代表這個 PR 的大方向已被核可。&lt;/p&gt;
&lt;p&gt;每個檔案所屬的資料夾都有對應的 &lt;code&gt;OWNERS&lt;/code&gt; 檔案，記錄著哪些檔案由哪些人擔任 Approver。機器人會確保 PR 修改到的每個檔案都有對應的 Approver 核可，才會加上這個標籤。&lt;/p&gt;
&lt;p&gt;跟 &lt;kbd&gt;lgtm&lt;/kbd&gt; 不同的是，就算檔案被修改過，&lt;kbd&gt;approved&lt;/kbd&gt; 標籤也不會消失。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-approve.jpg&quot; alt=&quot;使用 approve 指令&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;使用 approve 指令（&lt;a href=&quot;https://github.com/kubernetes/website/pull/35506&quot;&gt;k/website#35506&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;kbd&gt;cncf-cla: yes&lt;/kbd&gt; 是第三個不可或缺的標籤，在官方規則下，大家不該 review 沒有這標籤的 PR。&lt;/p&gt;
&lt;p&gt;為了確保免於未來潛在的法律爭議，大型專案通常都會要求貢獻者簽署 CLA 授權協議（Contributor License Agreement），只要照著指示一次性的簽署完畢就行了。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-cla.jpg&quot; alt=&quot;CLA 貢獻者授權協議&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;CLA 貢獻者授權協議（&lt;a href=&quot;https://github.com/kubernetes/website/pull/32897&quot;&gt;k/website#32897&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;負面標籤   {#negative-labels}&lt;/h2&gt;
&lt;p&gt;只要 PR 包含任一個負面標籤，就無法被自動合併。&lt;/p&gt;
&lt;p&gt;最常見的是，PR 作者與任何 Kubernetes 成員都可以使用的 &lt;kbd&gt;do-not-merge/hold&lt;/kbd&gt;。&lt;/p&gt;
&lt;p&gt;當遇到根本性的錯誤，會用 &lt;code&gt;/hold&lt;/code&gt; 來請作者特別注意，常見狀況是 git 操作錯誤，或動到不該動的檔案。&lt;/p&gt;
&lt;p&gt;也因為 PR 作者可以自己 &lt;code&gt;/unhold&lt;/code&gt; 解除，有時也會被用來作為讓 PR 作者自行控制何時被 merge 的工具，像是最後再次確認有沒有小地方要修改，或是部落格文章希望在哪天發佈。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-hold.jpg&quot; alt=&quot;被 hold 的實際狀況&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;被 hold 的實際狀況（&lt;a href=&quot;https://github.com/kubernetes/website/pull/34722&quot;&gt;k/website#34722&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在 commit 訊息中包含禁用關鍵字的話，則會出現 &lt;kbd&gt;do-not-merge/invalid-commit-message&lt;/kbd&gt;。&lt;/p&gt;
&lt;p&gt;由於專案中已經有 &lt;code&gt;@k8s-ci-robot&lt;/code&gt; 來做各種自動化事務了，為了避免意外發生，禁止在 commit 訊息中觸發原先 GitHub 提供的自動化操作。&lt;/p&gt;
&lt;p&gt;例如不能在 commit 中寫 &lt;code&gt;Fixes: #xxx&lt;/code&gt;、&lt;code&gt;Thanks @xxx&lt;/code&gt; 等，這些要移到 PR 說明欄。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-invalid-commit.jpg&quot; alt=&quot;無效的 commit 訊息&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;無效的 commit 訊息（&lt;a href=&quot;https://github.com/kubernetes/website/pull/34456&quot;&gt;k/website#34456&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;kbd&gt;needs-rebase&lt;/kbd&gt;，偵測到 merge conflict 時會自動加上此標籤，解決後這個標籤就會自動消失了。&lt;/p&gt;
&lt;p&gt;&lt;kbd&gt;do-not-merge/work-in-progress&lt;/kbd&gt;，只要在標題前面加上 &lt;code&gt;[WIP]&lt;/code&gt;，或透過 GitHub 介面設定為 Draft PR，就能得到這個標籤了。&lt;/p&gt;
&lt;h2&gt;分類標籤   {#triage-labels}&lt;/h2&gt;
&lt;p&gt;最直覺簡單的就屬檔案大小了，計算方式是新增的行數與刪除的行數相加。&lt;br&gt;
這可以幫大家快速判斷需要花多少時間 review，也提醒沒事不要塞一大坨更動，讓 PR 變成過於肥大。&lt;br&gt;
例如最小的 &lt;kbd&gt;size/XS&lt;/kbd&gt; 代表更動了 0 - 9 行，到修改超過 1000+ 行的 &lt;kbd&gt;size/XXL&lt;/kbd&gt;。&lt;/p&gt;
&lt;p&gt;根據不同的面向，會被標上不同的 SIG 特別興趣小組（special interest group）標籤：&lt;br&gt;
&lt;kbd&gt;sig/docs&lt;/kbd&gt;、&lt;kbd&gt;sig/release&lt;/kbd&gt;、&lt;kbd&gt;sig/security&lt;/kbd&gt;&lt;/p&gt;
&lt;p&gt;有些 PR 也會被標上屬於哪個領域：&lt;br&gt;
&lt;kbd&gt;area/blog&lt;/kbd&gt;、&lt;kbd&gt;area/web-development&lt;/kbd&gt;&lt;/p&gt;
&lt;p&gt;在各語言的資料夾中，會被標上語言標籤，方便在地化翻譯者們過濾：&lt;br&gt;
&lt;kbd&gt;language/zh&lt;/kbd&gt;、&lt;kbd&gt;language/en&lt;/kbd&gt;、&lt;kbd&gt;language/ko&lt;/kbd&gt;&lt;/p&gt;
&lt;p&gt;對於 issue，則是分為不同的種類：&lt;br&gt;
&lt;kbd&gt;kind/feature&lt;/kbd&gt;、&lt;kbd&gt;kind/bug&lt;/kbd&gt;、&lt;kbd&gt;kind/support&lt;/kbd&gt;、&lt;kbd&gt;kind/cleanup&lt;/kbd&gt;&lt;/p&gt;
&lt;h1&gt;社群成員身份   {#roles}&lt;/h1&gt;
&lt;p&gt;全球 500 萬名 Kubernetes 開發者的數量龐大，光是 k/website 就有 4,100 位貢獻者了，因此 k8s 社群也有一套相對成熟的權限機制。&lt;/p&gt;
&lt;h2&gt;身份總覽   {#role-overview}&lt;/h2&gt;
&lt;p&gt;在開始詳細介紹之前，先讓我快速整理一下 Kubernetes 組織中各身份擁有的大略權限。&lt;/p&gt;
&lt;h3&gt;(A) 任何人   {#role-anyone}&lt;/h3&gt;
&lt;p&gt;只要有 GitHub 帳號都可以發 PR、幫忙 review 給意見&lt;/p&gt;
&lt;h3&gt;(B) Member 組織成員   {#role-member}&lt;/h3&gt;
&lt;p&gt;可以用 &lt;code&gt;/lgtm&lt;/code&gt; 指令表示看過、沒問題&lt;/p&gt;
&lt;p&gt;也能用 &lt;code&gt;/close&lt;/code&gt;、&lt;code&gt;/hold&lt;/code&gt;、&lt;code&gt;/retitle&lt;/code&gt; 等指令管理 PR&lt;/p&gt;
&lt;h3&gt;(C) Reviewer 審核者   {#role-reviewer}&lt;/h3&gt;
&lt;p&gt;在有人發新的 Pull Request 時，bot 會隨機指派 2 位 Reviewer&lt;/p&gt;
&lt;h3&gt;(D) Approver 批准者   {#role-approver}&lt;/h3&gt;
&lt;p&gt;在 PR 被初步 review 過後，會指派 Approver 來做最終確認&lt;/p&gt;
&lt;p&gt;在 Approver 確認過大方向無誤後，可以用 &lt;code&gt;/approve&lt;/code&gt; 指令核可&lt;/p&gt;
&lt;h3&gt;(E) Tech Lead / Maintainer / Owner   {#role-owner}&lt;/h3&gt;
&lt;p&gt;有專案的管理權限、可以設定 &lt;code&gt;/milestone&lt;/code&gt; 指定合併的目標時間&lt;/p&gt;
&lt;h2&gt;如何開始這場冒險   {#start-contributing}&lt;/h2&gt;
&lt;p&gt;第一步當然是先熟悉社群、開 issue 發 PR，實際瞭解社群運作。&lt;/p&gt;
&lt;p&gt;在找到問題準備修復前，最好可以找 3 - 10 個 PR，看看大家是如何互動的，幫助自己更快融入社群。&lt;/p&gt;
&lt;h2&gt;Member 組織成員   {#member}&lt;/h2&gt;
&lt;p&gt;要成為 Member 的門檻非常低，只要發 5+ 個 PR，並找 2 位 Reviewer 協助背書（sponsor），就可以申請成為組織成員。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-apply-member.jpg&quot; alt=&quot;申請成為 Kubernetes 組織成員&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;申請成為 Kubernetes 組織成員（&lt;a href=&quot;https://github.com/kubernetes/org/pull/3440&quot;&gt;k/org#3440&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;很酷的一點是，Kubernetes 社群連 GitHub 組織成員都是用 git 管理、自動更新同步的，只要修改對應的 YAML 設定檔，&lt;code&gt;@k8s-ci-robot&lt;/code&gt; 就會自動寄發邀請函。&lt;/p&gt;
&lt;p&gt;接受邀請成為 Kubernetes 組織成員後，就有了 &lt;code&gt;/lgtm&lt;/code&gt; 半通過、&lt;code&gt;/close&lt;/code&gt; 關閉 PR、&lt;code&gt;/hold&lt;/code&gt; 要求暫緩等大多數的權限，可以隨時參與 PR review。&lt;/p&gt;
&lt;h2&gt;Reviewer 審核者   {#reviewer}&lt;/h2&gt;
&lt;p&gt;如果想成為 Reviewer 身份，規定上的最低限制是成為 Member 至少 3 個月，並且 review 過至少 20 個 PR。&lt;/p&gt;
&lt;p&gt;在自認對整個專案程式碼的大架構足夠熟悉後，就可以找 Approver 協助背書，送出申請。&lt;/p&gt;
&lt;p&gt;這邊的申請流程跟成為 Member 不同的是，申請的 PR 可以自己開就好，只要約 12 - 48 小時就能成功了。&lt;br&gt;
前面提到想成為 Member 的話需要先開 issue，等過了 3 - 30 天後負責人有空時，才會來批次處理加入申請。或許也跟 Member 身份門檻較低、申請數量過多有關吧。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-apply-reviewer.jpg&quot; alt=&quot;申請成為 Kubernetes 的 Reviewer&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;申請成為 Kubernetes 的 Reviewer（&lt;a href=&quot;https://github.com/kubernetes/org/pull/3436&quot;&gt;k/org#3436&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以 k/website 的中文語系為例，每當有新的 &lt;kbd&gt;language/zh&lt;/kbd&gt; PR 時，就會在 &lt;code&gt;sig-docs-zh-reviews&lt;/code&gt; 之中隨機指派兩個人為 PR reviewer，以確保在大家不會累死自己的前提下，每個 PR 都有人能幫忙處理。&lt;/p&gt;
&lt;p&gt;這身份承擔的責任在某些時候還蠻重的，但似乎沒有額外授予其他權限，比較像是願意為社群付出、為下一階段鋪路。&lt;/p&gt;
&lt;h2&gt;Approver 核可者   {#approver}&lt;/h2&gt;
&lt;p&gt;在擔任 Reviewer 至少 3 個月後，就可以由 Subproject Owner 提名為 Approver 了。&lt;/p&gt;
&lt;p&gt;擔任 Approver 必須在技術層面展現合理的判斷，為程式碼品質做高層次的把關，並作為新進貢獻者們的導師。&lt;/p&gt;
&lt;p&gt;願意在社群持續貢獻半年一年的志願者們，通常都能順利取得這個身份，相應的 &lt;code&gt;/approve&lt;/code&gt; 權限賦予 Approver 們決定 PR 能不能被合併到專案的權力。&lt;/p&gt;
&lt;h2&gt;Subproject Owner / Tech Lead / Maintainer / Admin   {#owner}&lt;/h2&gt;
&lt;p&gt;後續身份沒有一套通用的準則，在取得社群內大家的信任後，得到更多的權限也代表著更大的責任。&lt;/p&gt;
&lt;p&gt;像是我很好奇那幾位主要貢獻者們到底是怎麼管理時間的，都已經有正職工作了還有辦法投入那麼大的心力在開源貢獻。&lt;/p&gt;
&lt;h1&gt;後記   {#epilogue}&lt;/h1&gt;
&lt;p&gt;我在六月成功加入 Kubernets 組織，因為很喜歡這邊的社群氛圍，期間持續發 PR、幫別人 review，這段期間算是相對積極的貢獻者。&lt;/p&gt;
&lt;p&gt;剛成為 Member 才 2 個月的我，在上週被 k/website 最主要的維護者破例提名為 Approver 且通過了，讓我覺得非常驚喜。&lt;/p&gt;
&lt;p&gt;因此整理相關資訊分享給身邊的社群朋友們，希望未來有更多人一起加入，期待能做出更多有意義的貢獻。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://img.sean.taipei/2022/08/k8s-nominated.jpg&quot; alt=&quot;被提名為中文 Approver&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;被提名為中文 Approver（&lt;a href=&quot;https://github.com/kubernetes/website/pull/35563&quot;&gt;k/website#35563&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;本文同步分享於 &lt;a href=&quot;https://t.me/SeanChannel/106&quot;&gt;Telegram&lt;/a&gt;、
&lt;a href=&quot;https://www.facebook.com/Sean0604/posts/3256233521315151&quot;&gt;Facebook&lt;/a&gt;，
如果有什麼想法歡迎留言讓我知道。&lt;/p&gt;
&lt;p&gt;如果有興趣一起成為 Kubernetes 的貢獻者，歡迎加入
&lt;a href=&quot;https://t.me/CNTUG&quot;&gt;@CNTUG&lt;/a&gt;
群組一同交流。&lt;/p&gt;
&lt;h1&gt;參考連結   {#reference}&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;GitHub 專案連結：&lt;a href=&quot;https://github.com/kubernetes/website&quot;&gt;kubernetes/website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kubernetes 社群文件：&lt;a href=&quot;https://github.com/kubernetes/community/blob/master/community-membership.md&quot;&gt;Community membership&lt;/a&gt;、
&lt;a href=&quot;https://kubernetes.io/docs/contribute/&quot;&gt;Contribute to K8s docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;實戰教學文：&lt;a href=&quot;https://ndx.gitpages.daocloud.io/product/doc-template/zh/other/k8s-member.html&quot;&gt;快速成為 K8s Member&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;COSCUP 議程投影片：&lt;a href=&quot;https://speakerdeck.com/ydfu/how-to-start-contributing-to-kubernetes-projects&quot;&gt;How to start contributing to Kubernetes Projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
.post h3 {
    margin: -2px 0 6px 0;
}

.post table td {
    color: #666;
}

.post table td a {
    color: #6bf;
}

.post table td a:hover,
.post table td a:active,
.post table td a:focus {
    color: #8cf;
}
&lt;/style&gt;</content:encoded>
    </item>
  </channel>
</rss>
