<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Outvi V</title>
    <description>The latest articles on DEV Community by Outvi V (@outloudvi).</description>
    <link>https://dev.to/outloudvi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F67021%2F8157251c-73dc-48d2-8433-8691362b8757.png</url>
      <title>DEV Community: Outvi V</title>
      <link>https://dev.to/outloudvi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/outloudvi"/>
    <language>en</language>
    <item>
      <title>Contributing assets is never easy, but we have GitHub Actions</title>
      <dc:creator>Outvi V</dc:creator>
      <pubDate>Sat, 12 Sep 2020 02:16:04 +0000</pubDate>
      <link>https://dev.to/outloudvi/contributing-assets-is-never-easy-but-we-have-github-actions-2alm</link>
      <guid>https://dev.to/outloudvi/contributing-assets-is-never-easy-but-we-have-github-actions-2alm</guid>
      <description>&lt;p&gt;Yeh, we have been building a site of soundbites for monthes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://suisei.moe/"&gt;https://suisei.moe/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also yeh, collecting sound clips from videos is never easy. You need a good connection to YouTube. You need &lt;a href="https://github.com/ytdl-org/youtube-dl"&gt;&lt;code&gt;youtube-dl&lt;/code&gt;&lt;/a&gt;. You need &lt;a href="https://ffmpeg.org/"&gt;&lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt;. You also need to know how to use &lt;code&gt;ffmpeg&lt;/code&gt;. And sure, many fans (whoever want to contribute to this project) are Windows users and they don't know about anything above. So how to do the audio collection?&lt;/p&gt;

&lt;p&gt;Our idea is letting users contribute by simply commenting in a issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Procedure
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A contributor making comments.&lt;/li&gt;
&lt;li&gt;Our bot analyzes the comments, clip the audio and save it somewhere.&lt;/li&gt;
&lt;li&gt;Our bot replies the link to the contributor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a solution enough for the problem. After that, the contributor just downloads the file, fills in the metadata and makes a pull request to our project... wait, pull request?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;They are not used to the terminal and now you ask them to make a PR&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🤔&lt;/p&gt;

&lt;p&gt;Well... that's a problem. To ease the process, we need to avoid writing code for merely submitting an audio clip. This is where the GitHub action come:&lt;/p&gt;

&lt;h2&gt;
  
  
  A More User-friendly Procedure
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A contributor making comments.&lt;/li&gt;
&lt;li&gt;Our bot analyzes the comments, clip the audio and save it somewhere.&lt;/li&gt;
&lt;li&gt;Our bot replies the link to the contributor.&lt;/li&gt;
&lt;li&gt;An action detects the audio link.&lt;/li&gt;
&lt;li&gt;An action makes a PR with the audio link and the given metadata information.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is our solution!&lt;/p&gt;

&lt;p&gt;First, we &lt;a href="https://github.com/suisei-cn/sbtn-assets/issues/1#issuecomment-667538110"&gt;tell the metadata&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2O1v_2Ku--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5kclasnnoi0k489suhw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2O1v_2Ku--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5kclasnnoi0k489suhw4.png" alt="Commenting on a issue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally, the PR is &lt;a href="https://github.com/suisei-cn/starbuttons/pull/91"&gt;made&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KWjoB9Ke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8hdannfx9ebrbhb0ssub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KWjoB9Ke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8hdannfx9ebrbhb0ssub.png" alt="Creating PR"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tada! 🎉&lt;/p&gt;

&lt;p&gt;Last but not least, recently we &lt;a href="https://github.com/suisei-cn/starbuttons/releases/tag/v2.0.0"&gt;rebuilt the site&lt;/a&gt; with Svelte 3, making it faster to view and easier to maintain.&lt;/p&gt;

&lt;p&gt;Have a try on the brand-new ☄️&lt;a href="https://suisei.moe"&gt;https://suisei.moe&lt;/a&gt;!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post, as well as &lt;a href="https://dev.to/outloudvi/asset-download-upload-and-metadata-update-all-in-one-12m9"&gt;this post&lt;/a&gt;, is a part of the &lt;a href="https://dev.to/devteam/announcing-the-github-actions-hackathon-on-dev-3ljn"&gt;GitHub Actions Hackerthon&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
    </item>
    <item>
      <title>Asset download, upload and metadata update all in one</title>
      <dc:creator>Outvi V</dc:creator>
      <pubDate>Sat, 12 Sep 2020 01:00:56 +0000</pubDate>
      <link>https://dev.to/outloudvi/asset-download-upload-and-metadata-update-all-in-one-12m9</link>
      <guid>https://dev.to/outloudvi/asset-download-upload-and-metadata-update-all-in-one-12m9</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;This actions is designed to, with the help of a GitHub bot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accept clip and metadata input from a comment in issues&lt;/li&gt;
&lt;li&gt;Clip the asset according to the comment&lt;/li&gt;
&lt;li&gt;Download the asset and put it in the correct location (here begin the action part)&lt;/li&gt;
&lt;li&gt;Fill in the metadata&lt;/li&gt;
&lt;li&gt;Make a commit and push as a PR&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Auto&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PR&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;new&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sound"&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;issue_comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;created&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;edited&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push_to_branch_and_create_pr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create a PR with the sound&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(contains(github.event.comment.body,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pr&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'))&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;((contains(github.event.comment.author_association,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'OWNER')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;contains(github.event.comment.user.login,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'librehsbot'))&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(github.event.issue.number&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1))"&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-18.04&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check out current commit&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;suisei-cn/actions-download-file@v1&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;downloadfile&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download the file&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.comment.body }}&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assets&lt;/span&gt;
          &lt;span class="na"&gt;auto-match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;suisei-cn/actions-update-metadata@v2&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;updatemeta&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update sounds.yml&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.comment.body }}&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sounds.yml&lt;/span&gt;
          &lt;span class="na"&gt;default-username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;librehsbot&lt;/span&gt;
          &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yaml&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create Pull Request&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peter-evans/create-pull-request@v2.8.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;committer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Suisei Bot &amp;lt;noreply@suisei.moe&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.updatemeta.outputs.username }} &amp;lt;${{ steps.updatemeta.outputs.username }}@users.noreply.github.com&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;commit-message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;feat(sound):&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Add&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.downloadfile.outputs.filename&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;feat(sound):&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Add&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.downloadfile.outputs.filename&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;This is an automated sound addition PR. Netlify preview should be available soon, and a preview link should be shown.&lt;/span&gt;

            &lt;span class="s"&gt;&amp;lt;sub&amp;gt;Having problems? Check your [workflow](https://github.com/suisei-cn/sbtn-assets/blob/master/.github/workflows/auto_pr.yml).&amp;lt;/sub&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sound/new&lt;/span&gt;
          &lt;span class="na"&gt;branch-suffix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;random"&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;new-sound&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/suisei-cn/sbtn-assets/blob/master/.github/workflows/auto_pr.yml"&gt;auto_pr.yml&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/suisei-cn"&gt;
        suisei-cn
      &lt;/a&gt; / &lt;a href="https://github.com/suisei-cn/sbtn-assets"&gt;
        sbtn-assets
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Starbuttons assets.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Starbuttons Assets&lt;/h1&gt;
&lt;p&gt;This repository saves assets of &lt;a href="https://github.com/suisei-cn/starbuttons"&gt;starbuttons&lt;/a&gt; since &lt;code&gt;starbuttons@2.0.0&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
Contributing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sounds update: &lt;a href="https://github.com/suisei-cn/sbtn-assets/blob/master/sounds.yml"&gt;&lt;code&gt;sounds.yml&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Category update: &lt;a href="https://github.com/suisei-cn/sbtn-assets/blob/master/categories.yml"&gt;&lt;code&gt;categories.yml&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sound assets: &lt;a href="https://github.com/suisei-cn/sbtn-assets/tree/master/assets"&gt;&lt;code&gt;assets/&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/suisei-cn/sbtn-assets"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Two written actions with this action:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/suisei-cn/actions-download-file"&gt;actions-download-file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/suisei-cn/actions-update-metadata"&gt;actions-update-metadata&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The GitHub bot: &lt;a href="https://github.com/suisei-cn/pvp-clipbot"&gt;pvp-clipbot&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>actionshackathon</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Transparent proxy on Arch Linux, with iptables and systemd slice</title>
      <dc:creator>Outvi V</dc:creator>
      <pubDate>Tue, 25 Feb 2020 12:16:24 +0000</pubDate>
      <link>https://dev.to/outloudvi/transparent-proxy-on-arch-linux-with-iptables-and-systemd-slice-580c</link>
      <guid>https://dev.to/outloudvi/transparent-proxy-on-arch-linux-with-iptables-and-systemd-slice-580c</guid>
      <description>&lt;p&gt;Long story short. To build a transparent proxy, we need to redirect every outbound request to the proxy. It seems easy with iptables... wait a second, no. Outbound requests from the proxy should not be redirected, or nothing can be sent out. How to do that? Usually an exception on the proxy server IP is set. But what if you have multi proxy servers? What if your proxy servers are changing overtime? Wouldn't it be a pain editing iptables rules?&lt;/p&gt;

&lt;p&gt;Well, we have &lt;code&gt;cgroups&lt;/code&gt;. We can put our proxy program in a cgroup, and give an exception to this cgroup on iptables. On Arch Linux, the easist way to create cgroups is via &lt;code&gt;systemd&lt;/code&gt;. Therefore, we are picking the systemd &lt;em&gt;PANTS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here shows an example for a TCP IPv4 transparent proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a slice, and put stuffs in
&lt;/h2&gt;

&lt;p&gt;If your proxy program runs as a systemd service, you can add this "Slice=" line to its configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Service]
Slice=bypass.slice
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After daemon-reloading and restarting, your proxy program will be in the "bypass.slice" group.&lt;/p&gt;

&lt;p&gt;You can also see a new directory named bypass.slice in &lt;code&gt;/sys/fs/cgroup/unified/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ls /sys/fs/cgroup/unified/bypass.slice/
cgroup.controllers  cgroup.max.descendants  cgroup.threads  io.pressure
cgroup.events       cgroup.procs            cgroup.type     memory.pressure
cgroup.freeze       cgroup.stat             cpu.pressure    run-u1925.scope/
cgroup.max.depth    cgroup.subtree_control  cpu.stat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If your proxy program is not a systemd service, run it with &lt;code&gt;systemd-run&lt;/code&gt;：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemd-run &lt;span class="nt"&gt;--slice&lt;/span&gt; bypass.slice &lt;span class="nt"&gt;--scope&lt;/span&gt; clash &lt;span class="nt"&gt;-c&lt;/span&gt; /etc/clash/config.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;--scope&lt;/code&gt; so that you can see the stdouts and manipulate on stdins. It requires root permission (or not if you are using cgroups v2?). I would think you have got the root permission, since we're editing &lt;code&gt;iptables&lt;/code&gt; later!&lt;/p&gt;

&lt;p&gt;The same way if you want to start an application which bypasses the proxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemd-run &lt;span class="nt"&gt;--slice&lt;/span&gt; bypass.slice &lt;span class="nt"&gt;--scope&lt;/span&gt; firefox
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or a shell which bypasses the proxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemd-run &lt;span class="nt"&gt;--slice&lt;/span&gt; bypass.slice &lt;span class="nt"&gt;--scope&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Have a try
&lt;/h3&gt;

&lt;p&gt;Let's run a ping in a slice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo systemd-run --slice test2.slice --scope -S
Running scope as unit: run-r7865e1749deb48e4bcf797f1f403f396.scope
$ ping 1.1.1.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The ping is running here. Now we block all outbound packets from this slice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-A&lt;/span&gt; OUTPUT &lt;span class="nt"&gt;-m&lt;/span&gt; cgroup &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="s2"&gt;"test2.slice"&lt;/span&gt; &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The ping will start to fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ping: sendmsg: Operation not permitted
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Okay. We see that iptables are working with our slice (cgroup). Now delete the rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-L&lt;/span&gt; OUTPUT &lt;span class="nt"&gt;--line-numbers&lt;/span&gt;
&lt;span class="c"&gt;# Find something like&lt;/span&gt;
&lt;span class="c"&gt;#  "2 DROP   all  --  anywhere  anywhere  cgroup test2.slice"&lt;/span&gt;
&lt;span class="c"&gt;# and remember its number&lt;/span&gt;
iptables &lt;span class="nt"&gt;-D&lt;/span&gt; OUTPUT 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  iptables' time!
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Parts of this paragraph comes from &lt;a href="https://github.com/Dreamacro/clash/issues/158"&gt;Dreamacro/clash#158&lt;/a&gt; and &lt;a href="https://ivo-wang.github.io/2018/02/24/TP-redir/"&gt;this&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a chain on the nat table.&lt;/span&gt;
&lt;span class="c"&gt;# Why nat table? Because we are doing redirects later.&lt;/span&gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-N&lt;/span&gt; TP-TCP

&lt;span class="c"&gt;# On this chain:&lt;/span&gt;
&lt;span class="c"&gt;# 1. Everything from the bypass.slice should be where they were&lt;/span&gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-m&lt;/span&gt; cgroup &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="s2"&gt;"bypass.slice"&lt;/span&gt; &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
&lt;span class="c"&gt;# 2. Everything to local &amp;amp; loopback address should be where they were&lt;/span&gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 0.0.0.0/8 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 127.0.0.0/8 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 10.0.0.0/8 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 169.254.0.0/16 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 172.16.0.0/12 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 192.168.0.0/16 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 224.0.0.0/4 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-d&lt;/span&gt; 240.0.0.0/4 &lt;span class="nt"&gt;-j&lt;/span&gt; RETURN
&lt;span class="c"&gt;# 3. Everything else should go thourh the proxy port&lt;/span&gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; TP-TCP &lt;span class="nt"&gt;-p&lt;/span&gt; tcp &lt;span class="nt"&gt;-j&lt;/span&gt; REDIRECT &lt;span class="nt"&gt;--to-ports&lt;/span&gt; 7892
&lt;span class="c"&gt;# 4. All output packets should go through TP-TCP chain&lt;/span&gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; OUTPUT &lt;span class="nt"&gt;-p&lt;/span&gt; tcp &lt;span class="nt"&gt;-j&lt;/span&gt; TP-TCP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Do some &lt;code&gt;curl&lt;/code&gt;s and see if they are going through the proxy. Also, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iptables -L TP-TCP -t nat -v -n 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;to see if any &lt;code&gt;pkts&lt;/code&gt; and &lt;code&gt;bytes&lt;/code&gt; is going through. If it works, we're done! Hooray! 🎉&lt;/p&gt;

</description>
      <category>linux</category>
      <category>iptables</category>
      <category>cgroups</category>
      <category>proxy</category>
    </item>
  </channel>
</rss>
