Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Online config URL parsing #21

Merged
merged 9 commits into from
Jun 26, 2021
Merged

Online config URL parsing #21

merged 9 commits into from
Jun 26, 2021

Conversation

alalamav
Copy link
Contributor

@alalamav alalamav commented Apr 5, 2021

  • Implements SIP008 URL encoding per the shadowsocks community spec.
  • Uses the ssconf URL protocol to support encoding parameters.
  • Adds unit tests.

@alalamav alalamav self-assigned this Apr 5, 2021
// The built-in URL parser throws as desired when given URIs with invalid syntax.
const urlParserResult = new URL(inputForUrlParser);
// Use ValidatedConfigFields subclasses (Host, Port, Tag) to throw on validation failure.
const uriFormattedHost = urlParserResult.hostname;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do a regex replace like ...hostname.replace(/\[(.*)\]/, '$1') here then we don't need the try-catch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately that doesn't quite work because some implementations fail without the brackets. I don't remember for which browsers/webviews we added the try catch in SIP002, but I thought it would make sense to replicate it here.

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
Copy link
Contributor Author

@alalamav alalamav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the review!

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
// The built-in URL parser throws as desired when given URIs with invalid syntax.
const urlParserResult = new URL(inputForUrlParser);
// Use ValidatedConfigFields subclasses (Host, Port, Tag) to throw on validation failure.
const uriFormattedHost = urlParserResult.hostname;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately that doesn't quite work because some implementations fail without the brackets. I don't remember for which browsers/webviews we added the try catch in SIP002, but I thought it would make sense to replicate it here.

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
Copy link

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move away from the SIP008 name. That's more focused on the file format, not the url format.

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
}

// Ref: https://github.com/shadowsocks/shadowsocks-org/issues/89
export const SIP008_URI = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should call this SIP008_URI. The SIP0008 is a bad standard. It's focused on the config format, not the URL format. They are conflating many things there. And we are kind of making it our own format.

Why do you need this object? Can't you just expose the method? I'd rename parse as parseOnlineConfigUrl to get ConfigFetchParams.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in b3f2f19

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SIP0008 is a bad standard. It's focused on the config format, not the URL format.

SIP008 is focused on the config format because all existing solutions widely used by providers in China are just some random JSON encoded in base64 and then served by a typical web server. SIP008 was intended to address the situation by providing a standard JSON document format that is flexible and not encoded in any unnecessary means like base64.

As for the URL format, most people I know who set up their own servers for such purposes already own at least one domain name. And it's pretty easy to obtain a TLS certificate with Let's Encrypt. But I do agree utilizing self-signed certificates can be better in some situations, and that's why I mentioned this PR when discussing with V2Fly developers on V2Ray's upcoming subscription protocol that's based on SIP008ext with a custom URL format.

And we are kind of making it our own format.

I'm open to amendments to SIP008. What Outline plans to implement can be useful to the community as well. We are working towards the same goal after all.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, I think I misspoke there. The standard meets a different need than the one in Outline, so it's bad for our use case.

  1. It doesn't address the need for the certificate fingerprint
  2. It doesn't address the need to handle redirects in a way that allows migration of the config location
  3. It doesn't address the need for a special URI protocol for better user experience
  4. The file format is overly complicated with many things we don't actually support. It includes thinks that are not config, like "bytes used". It has flaws like not knowing what can be safely ignored. Configuring services need more careful consideration, but we'd like to punt on that for now.

I've argued for all of those items in the SIP discussions. I'd like to implement what works for Outline, and then go back with it as a proof of concept.

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
Copy link
Contributor Author

@alalamav alalamav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review.

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
}

// Ref: https://github.com/shadowsocks/shadowsocks-org/issues/89
export const SIP008_URI = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in b3f2f19

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
@alalamav alalamav requested a review from fortuna April 12, 2021 23:06
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
}

// Ref: https://github.com/shadowsocks/shadowsocks-org/issues/89
export const SIP008_URI = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, I think I misspoke there. The standard meets a different need than the one in Outline, so it's bad for our use case.

  1. It doesn't address the need for the certificate fingerprint
  2. It doesn't address the need to handle redirects in a way that allows migration of the config location
  3. It doesn't address the need for a special URI protocol for better user experience
  4. The file format is overly complicated with many things we don't actually support. It includes thinks that are not config, like "bytes used". It has flaws like not knowing what can be safely ignored. Configuring services need more careful consideration, but we'd like to punt on that for now.

I've argued for all of those items in the SIP discussions. I'd like to implement what works for Outline, and then go back with it as a proof of concept.

src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
src/shadowsocks_config.ts Outdated Show resolved Hide resolved
@alalamav alalamav changed the title SIP008 online config Online config URL parsing Apr 15, 2021
Copy link

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing

// The default URL parser fails to recognize the default HTTPs port (443).
const port = new Port(urlParserResult.port || '443');
// Parse extra parameters from the tag, which has the URL search parameters format.
const tag = new Tag(decodeURIComponent(urlParserResult.hash.substring(1)));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are double decoding, which will break with the value has an encoded &, for example: 'https://dsfdsf.com#foo=a%26b'

Remove the decodeURIComponent call since URLSearchParams already decodes for you.

Also add a test for that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Done in fb81d34.

@alalamav alalamav merged commit dc61106 into master Jun 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants